Intel Core & Enhanced Core微架構(6)
Instruction PreDecode
指令預譯碼器從指令Cache或者指令預取快取區中接收16位元組的指令流,執行如下的預譯碼操作:
- 確定每條指令的長度(注:x86指令是變長指令)
- 譯碼每條指令的指令字首
- 為譯碼器標記每條指令的不同屬性(例如,“是分支指令”)
指令預譯碼器可以每個週期想指令佇列寫入6條x86指令。如果讀取的指令行含有超過6條指令,預譯碼器每個週期譯碼6條指令,直到指令行中所有的指令都譯碼完畢。然後才開始譯碼下一個指令行。
例如,如果一個指令行含有7條指令,預譯碼器在第一個週期會譯碼前6條指令,然後在第二個週期譯碼1條指令。平均下來,每個週期譯碼3.5條指令。儘管看起來每週期指令數(IPC)指標沒有完全優化(即沒有達到理想的每週期6條指令),但是實際上這個速度已經高出大部分程式的效能了。通常情況下,軟體無需為了避免指令飢餓而採取額外的優化措施。
在指令長度譯碼階段,下面的指令字首可能會導致效能問題。這些字首可以動態的改變指令的長度,被稱為指令長度切換字首(LCP):
- 運算元長度覆蓋字首(66H), 當指令使用單字長立即數時,這個字首位於指令前
例如指令MOV ax, 1234H對應的十六機制機器碼是66 B8 34 12(66即是運算元長度覆蓋字首)
- 地址長度覆蓋字首(67H),在真實模式,16位或32位保護模式下,當指令使用ModR/M位元組時。
例如,指令MOV eax, [si]對應的十六進位制機器碼是"67 8B 04"(67即使地址長度覆蓋字首)
當預譯碼器在指令行中碰到LCP字首時,它必須使用一個慢速的指令長度譯碼演算法。使用這個演算法,預譯碼器需要6個週期才能完成指令行譯碼,而不是通常的1個週期完成。而且通常的處理器流水線中的排隊機制也無法隱藏/覆蓋LCP字首導致的額外週期數。
注意,在Intel 64位架構指令集中的REX字首(4xH)可以改變兩類指令的長度:MOV指令的位移量和MOV指令的立即數。但是這個字首並不會導致LCP損失,因此它不被認為是LCP字首。(todo:補充一個例子)
Instruction Queue
指令佇列是18指令深度,即有18個條目,可以儲存18條指令,位於指令預譯碼器與指令譯碼器之間。它每個週期可以傳送最多達5條指令,同時支援1個巨集熔合操作。指令佇列也可以作為小於18條指令的迴圈的快取記憶體(簡稱為迴圈快取)使用,具體操作後面有講解。
BPU中有一個迴圈流偵測器(LSD)。這個LSD可以嘗試偵測迴圈指令,符合條件的迴圈結構的指令會被鎖定在指令佇列中,至此迴圈指令可以由指令佇列提供,直到分支預測失敗導致迴圈結束。當迴圈指令在指令佇列中“回放”時,即指令佇列(向執行核)提供迴圈指令,可以獲得更高的指令頻寬以及更低的功耗(因為流水線前端中的其他部件可以關閉,例如取指單元,預譯碼器等)。
LSD提供瞭如下的優勢:
- 對於採納分支沒有頻寬損失
- 對於未對齊的指令沒有頻寬損失
- 沒有LCP損失,因為預譯碼階段已經完成
- 降低前端的能耗,因為指令Cache,BPU以及預譯碼器可以空閒
軟體應該“機會主義式地”使用迴圈快取功能。迴圈展開以及其他的優化方法可能導致迴圈長度太大,以至於無法符合LSD條件。對於追求高效能的程式碼,迴圈展開通常是更被推薦的優化方法,儘管這種方法可能導致LSD不可用。
Instruction Decode
Intel Core微架構有4個指令譯碼器,第一個,譯碼器0,可以譯碼最多4微指令的Intel 64與IA32指令,即譯碼器0將x86指令譯碼後對應的微指令條數不超過4條。另外3個譯碼器可以譯碼單微指令的x86指令,即一條x86指令譯碼後對應一條微指令。微指令序列生成器可以每週期生成3條微指令,輔助譯碼超過4微指令的x86指令。
注:Intel Architecture Optimization (Order#: 245127-001)的附錄C中介紹了Pentium II & III處理器上常用指令對應的微指令條數。大部分x86指令都對應單條微指令,例如AAA,CLC,CMC,DAS等,複雜的指令,例如AAM,RET等,對應4條微指令。更復雜的指令,例如RSM,STI等,則需要微指令序列生成器輔助譯碼。需要注意的是,同一條指令的不同格式,可能會生成不同條數的微指令,例如ADD指令,ADD AL, imm8對應單條微指令,ADD r8, m8對應2條微指令(大約是讀運算元,然後做加法),ADD m8, imm8則對應4條微指令(大約是讀運算元,做加法,再寫回記憶體)。Intel並未公佈微指令的細節,以及單條x86指令對應的詳細微指令序列。
所有的譯碼器都支援單微指令流的常見情況,包括:微熔合,棧指標跟蹤,和巨集熔合。因此,即使那3個簡單譯碼器也不僅限於譯碼單微指令的x86指令。將指令按照4-1-1-1的模式排列既無必要也不再推薦。
巨集熔合將兩條x86指令合併成單條微指令。在32位操作模式下(包括Intel 64位模式下的相容模式),Intel Core微架構可以每週期進行一次巨集熔合;但是在64位模式下不做巨集熔合,因為使用長指令(指令位元組數)的程式碼通常很難利用到巨集熔合機制。
注:處理器的Intel 64位模式實際包括兩種子模式:相容(子)模式和64位(子)模式。相容模式使得64位作業系統可以執行傳統的32位軟體;64位模式使得64位作業系統可以執行訪問64位線性地址空間的64位應用程式。