您的位置 首页 产品

ARM3级流水和5级流水为什么都是PC=PC+8

首先介绍前置知识arm7采用三级流水(1)取指(fetch)取指级的任务是从程序存储器中读取指令。(2)译码(decode)译码级完成对指令的分析…

首要介绍前置常识

arm7选用三级流水
(1)取指(fetch)
取指级的使命是从程序存储器中读取指令。
(2)译码(decode)
译码级完结对指令的剖析,并为下一个周期预备数据途径需求的操控信号。在这一级,指令占用译码逻辑,不占用数据通路。
(3)履行(excute)
完结指令要求的操作,并依据需求将成果写回寄存器。指令占用数据途径,寄存器堆被读取,操作数在桶行移位器中被移位。运算器发生运算成果并回写到意图寄存器中,运算器依据指令需求和运送成果更改状况寄存器的条件位。

arm9选用五级流水
(1)取指(fetch)

从存储器中取出指令,并将其放入指令流水线。

(2)译码(decode)

指令被译码,从寄存器堆中读取寄存器操作数。在寄存器堆中有3个操作数读端口,因而大多数ARM指令能在1个周期内读取其操作数。

(3)履行(execute)

将其中一个操作数移位,并在ALU中发生成果。假如指令是Load或Store指令,则在ALU中核算存储器的地址。

(4)缓冲/数据(buffer/data)

假如需求则拜访数据存储器,不然ALU仅仅简略地缓冲一个时钟周期,以便是一切的指令具有相同的流水线流程。

(5)回写(write-back)寄存器堆

————————————————

留意,arm7中履行和取指是隔了一级译码级,那一级不读取数据,当时PC=原PC+8, 正常
arm9中履行和取指之间的译码级不再厚道,译码级现已开端从寄存器堆中读取寄存器操作数,这样的话,
读取到得便是PC+4,不是PC+8,履行级又不会再读一次,那将导致履行级的PC仍是=PC+4
为了坚持向下兼容,在ARM9的5级流水线上,取指级添加的PC值被直接送到译码级的寄存器,穿过了两级之间的流水线寄存器,这样译码级得到的PC值便是下一条指令的PC+4,等于当时指令的PC+8,
等到了履行级时,PC寄存器的值=当时指令地址+8

当运用指令STR或STM对R15进行保存时,保存的可能是当时指令地址加8或当时指令地址加12。
到底是哪种方法,取决于芯片的详细规划方法。当然,在同一个芯片中,只能选用一种方法。要么保存当时指令地址加8,要么保存当时指令地址加12。程序开发人员应尽量防止运用STR或STM指令来对R15进行操作。当不可防止要运用这种方法时,能够先经过一小段程序来确认所运用的芯片是运用哪种方法完成的。例如:
SUB R1,PC, #4 ;R1中寄存STR指令地址
STR PC,[R0] ;用STR指令将PC保存到R0指向的地址单元中,
;PC=STR指令地址+偏移量(偏移量为8或许12)。
LDR R0,[R0] ;读取STR指令地址+偏移量的值
SUB R0,R0,R1 ; STR指令地址+偏移量的值减去STR指令的地址,
;得到偏移量值(8或许12)。

=============================

ARM7选用三级流水线的冯·诺伊曼结构,ARM9选用五级流水线的哈佛结构。

ARM7流水线包含取指(fetch)、译码(decode)、履行(excute)。ARM7流水线在译码阶段不读取操作数寄存器,因而履行阶段的PC值和取指阶段的PC值关系为:PC(excute)=PC(fetch)+8。

ARM9流水线包含取指(fetch)、译码(decode)、履行(excute)、缓冲/数据(buffer/data)、回写(write-back)寄存器堆。ARM9流水线在译码阶段现已开端读取操作数寄存器,因而译码阶段的PC值和取指阶段的PC值关系为:PC(decode)=PC(fetch)+4。因而履行阶段的PC值和译码阶段的PC值关系为:PC(excute)=PC(decode)+4。

为了确保ARM9流水线和ARM7流水线兼容,ARM9流水线将取指阶段的PC值跨过取指和译码流水线寄存器,直接送往译码阶段寄存器,这样依然确保履行阶段的PC值和取指阶段的PC值关系为:PC(excute)=PC(fetch)+8。


以下面uboot中的start.S的最开端的汇编代码为例来进行解说:

00000000 <_start>:
0: ea000014 b 58
4: e59ff014 ldr pc, [pc, #20] ; 20 <_undefined_instruction>
8: e59ff014 ldr pc, [pc, #20] ; 24 <_software_interrupt>
c: e59ff014 ldr pc, [pc, #20] ; 28 <_prefetch_abort>
10: e59ff014 ldr pc, [pc, #20] ; 2c <_data_abort>
14: e59ff014 ldr pc, [pc, #20] ; 30 <_not_used>
18: e59ff014 ldr pc, [pc, #20] ; 34 <_irq>
1c: e59ff014 ldr pc, [pc, #20] ; 38 <_fiq>
00000020 <_undefined_instruction>:
20: 00000120 .word0x00000120
仿制代码

下面临每一个指令周期,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。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/chanpin/274661.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部