【轉】ARM獲得PC指針爲何PC=PC+8[下](轉)

【轉】ARM獲得PC指針爲何PC=PC+8[下](轉)

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 <reset>
  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,會繼續執行完成。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章