【轉】ARM的三級流水線結構

3.4爲何ARM7中PC=PC+8

此處解釋爲何ARM7中,CPU地址,即PC,爲何有PC=PC+8這一說法:

衆所周知,AMR7,是三級流水線,其細節見圖:

圖 3.1. AMR7三級流水線

AMR7三級流水線

 

首先,對於ARM7對應的流水線的執行情況,如下面這個圖所示:

 

圖 3.2. ARM7三級流水線狀態

ARM7三級流水線狀態

 

然後對於三級流水線舉例如下:

 

圖 3.3. ARM7三級流水線示例

ARM7三級流水線示例

 

從上圖,其實很容易看出,第一條指令:

 

add r0, r1,$5

執行的時候,此時PC已經指向第三條指令:

cmp r2,#3

的地址了,所以,是PC=PC+8.

3.4.1. 爲何ARM9和ARM7一樣,也是PC=PC+8

ARM7的三條流水線,PC=PC+8,很好理解,但是AMR9中,是五級流水線,爲何還是PC=PC+8,而不是

PC

=PC+(5-1)*4

=PC + 16,

呢?

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

具體解釋之前,先貼上ARM7和ARM9的流水線的區別和聯繫:

圖 3.4. ARM7三級流水線 vs ARM9五級流水線

ARM7三級流水線 vs ARM9五級流水線

 

圖 3.5. ARM7三級流水線到ARM9五級流水線的映射

ARM7三級流水線到ARM9五級流水線的映射

 

下面開始對爲何ARM9也是PC=PC+8進行解釋。

先列出ARM9的五級流水線的示例:

圖 3.6. ARM9的五級流水線示例

ARM9的五級流水線示例

 

舉例分析爲何PC=PC+8

然後我們以下面uboot中的start.S的最開始的彙編代碼爲例來進行解釋:

00000000 <_start>:
   0:	ea000014 	b	58 <reset>
   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 	.word	0x00000120
        

下面對每一個指令週期,CPU做了哪些事情,分別詳細進行闡述:

在看下面具體解釋之前,有一句話要牢記,那就是:

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

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

認識清楚了這個前提,後面的舉例講解,就容易懂了。

  1. 指令週期Cycle1
    1. 取指

      PC總是指向將要讀取的指令的地址(即我們常說的,指向下一條指令的地址),而當前PC=4,

      所以去取物理地址爲4對對應的指令

      ldr	pc, [pc, #20]

      其對應二進制代碼爲e59ff014。

      此處取指完之後,自動更新PC的值,即PC=PC+4(單個指令佔4字節,所以加4)=4+4=8

  2. 指令週期Cycle2
    1. 譯指

      翻譯指令e59ff014

    2. 同時再去取指

      PC總是指向將要讀取的指令的地址(即我們常說的,指向下一條指令的地址),而當前PC=8,

      所以去物理地址爲8所對應的指令“ldr pc, [pc, #20]” 其對應二進制代碼爲e59ff014。

      此處取指完之後,自動更新PC的值,即PC=PC+4=8+4=12=0xc

  3. 指令週期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了。

 

用圖來說明PC=PC+8個過程

對於上面的文字的分析過程,可能看起來不是太容易理解,所以,下面這裏通過圖表來表示具體的流程,就更容易看懂了。其中,下圖,是以ARM9的五級流水線的內部架構圖爲基礎,而編輯的出來用於說明爲何ARM9的五級流水線,也是PC=PC+8:

圖 3.7. ARM9的五級流水線中爲何PC=PC+8

ARM9的五級流水線中爲何PC=PC+8

 

對於上圖中的,第一個指令在執行的時候,是使用到了PC的值,其實,我們可以看到,

對於指令在執行中,不論是否用到PC的值,PC都會按照既定邏輯,沒一個cycle,自動增加4的,套用《非誠勿擾2》中的經典對白,即爲:

你(指令執行的時候)用,

或者不用,

PC就在那裏,

自動增4

所以,經過兩個cycle的增4,就到了指令執行的時候,此時PC已經增加了8了,即使你指令執行的時候,沒有用到PC的值,其也還是已經加了8了。而一般來說,大多數的指令,肯定也都是沒有用到PC的,但是其實任何指令執行的那一時刻,也已經是PC=PC+8,而多數指令沒有用到,所以很多人沒有注意到這點罷了。

 

[提示] PC(execute)=PC(fetch)+ 8

對於PC=PC+8中的兩個PC,其實含義不完全一樣.其更準確的表達,應該是這樣:

PC(execute)=PC(fetch)+ 8

其中:

PC(fetch):當前正在執行的指令,就是之前取該指令時候的PC的值

PC(execute):當前指令執行的計算中,如果用到PC,則此時PC的值。

[提示] 不同階段的PC值的關係

對應地,在ARM7的三級流水線(取指,譯指,執行)和ARM9的五級流水線(取指,譯指,執行,存儲,寫回)中,可以這麼說:

PC, 總是指向當前正在被取指的指令的地址,

PC-4,總是指向當前正在被譯指的指令的地址,

PC-8,總是指向當前的那條指令,即我們一般說的,正在被執行的指令的地址。

 

【總結】

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

 

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