免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
解讀 Intel? Microarchitecture
以 Intel? sandy bridge 微架構(gòu)為例,了解一下 Intel 近代微架構(gòu)。
上圖是 Intel? sandy bridge 微架構(gòu)的流水線示意圖,實行了“發(fā)射-執(zhí)行-完成”相分離包括下面的組件(亂序執(zhí)行按序完成):
in-order front-end:程序執(zhí)行順序的前端組件,包括了: L1 ICache 與 ITLB ,指令通過 ITLB 查找 fetch(提取)進入到 32K 的 L1 指令 cache。
pre-decoder,一個預解碼器,主要用來解析指令的長度,處理 LCPs(length changing prefixes)。
instruction queue,經(jīng)過初步解析后存放的指令隊列。
decoder,4個解碼器。其中一個為復雜解碼器,能解碼所有 x86/x64 指令。三個簡單解碼器,負責解碼為一個 micro-op。
decoded ICache,解碼后的 uops(micro-ops)cache。
MSROM(microcode sequencer ROM),一個 microcode sequencer ROM(微代碼裝置 ROM),存放復雜指令的 micro-op 流。
BPU(branch prediction unit),分支預測單元。
micro-op queue,排列 decoded ICache 的 uops。
out-of-order engine,亂序發(fā)射的引擎組件,包括了: allocater/renamer,資源分配器與重命名器。Renamer 將 x86 架構(gòu)性(architectural)的源/目標操作數(shù)(寄存器)重命令為微架構(gòu)性(microarchitectural)源/目標操作數(shù)(寄存器),解決 uops 間的 false-dependencies(假依賴),并形成 out-of-order 的“data flow”(數(shù)據(jù)流)發(fā)送到 scheduler。 Allocater 分配 uops 需要的 load buffer 以及 store buffer。
scheduler,調(diào)度器。等待資源可用(dispatch port 可用,read buffer 或者 store buffer 可用)以及 uop 的操作數(shù)已經(jīng)準備好后,將 uop 綁定到相應(yīng) dispatch port 后分派到執(zhí)行單元。scheduler 每個 cycle 最多可以分派 6 個 uops 到執(zhí)行 port。
in-order retirement,按序完成單元。使用 reorder buffer 保存 uops 各個階段的結(jié)果,確保 uops 的執(zhí)行結(jié)果(包括任何可能遇到的異常,中斷)按原始程序的次序完成。
execution unit,執(zhí)行單元,含有 6 個執(zhí)行 port 以及 3 個類型的 stack。因此,schedular 每個 cycle 最多可以調(diào)度并分派 6 個 uops 到執(zhí)行 port。
cache hierarchy,包括下面: L1 DCache:
DCU(data cache unit)
load buffers
store buffers
line fill buffers
L1 ICache
L2 cache
LLC(last level cahce)
1. in-order front-end
在按序前端里,包括了下面的組件:
L1 ICache 與 ITLB ,通過 ITLB 查找 fetch(提取)進入到 32K 的 L1 ICache。
legacy decode pipeline,下面的組件被劃分到 legacy decode pipeline 里:
pre-decoder,一個預解碼器,主要用來解析指令的長度,處理 LCPs(length changing prefixes)。
instruction queue,經(jīng)過初步解析后存放的指令隊列。
decoder,4個解碼器。其中一個為復雜解碼器,能解碼所有 x86/x64 指令。三個簡單解碼器,負責解碼為一個 micro-op。
decoded ICache,解碼后的 uops(micro-ops)cache。
MSROM(microcode sequencer ROM),一個 microcode sequencer ROM(微代碼裝置 ROM),存放復雜指令的 micro-op 流。
BPU(branch prediction unit),分支預測單元。
micro-op queue,排列 decoded ICache 的 uops。
1.1 ICache 與 ITLB
在指令提取(instruction fetch)階段,處理器通過 ITLB 查找并從內(nèi)存的 16-byte 邊界上提取指令到 ICache 里。當 ICache hit 時引發(fā) ICache 每個 cycle 傳送 16 bytes 到指令 pre-decoder 組件里。如果以平均每條指令 4 個字節(jié)來算,那么 ICache 能滿足每個周期 4 個 decoder 的解碼工作??梢哉J為,如果遇到較長指令的話(例如 10 個字節(jié)),ICache 傳送的 16 bytes 是不能滿足 decoder 的。
在 sandy bridge 微架構(gòu)上,ICache 與 ITLB 的明細信息:
size: 32-Kbyte
ways: 8
ITLB 4K-page entries:128
ITLB large-page(2M/1G)entries:8
也就是說,ICache 共有 32K,8-ways 結(jié)構(gòu)。ITLB 中維護 4K 頁面映射結(jié)果的表項有 128 個,維護 2M 與 1G 頁面映射結(jié)果的表項共有 8 個。當產(chǎn)生 ITLB miss 時,處理器將在 STLB(second TLB,或者 shared TLB)里繼續(xù)查找。ITLB miss 而在 STLB hit 時,所需要 7 個 cycles。當然,如果 STLB 也產(chǎn)生 miss 則需要在頁表結(jié)構(gòu)里進行 walk,將需要更多的 cycles。
1.2 pre-decoder
pre-decoder 接收從 ICache 發(fā)送過來 16 bytes 的指令,它主要執(zhí)行下面的工作:
確定指令的具體長度。
處理指令所有的 prefix。
標記指令的類型屬性。(例如:屬于分支指令)
pre-decoder 在每個 cycle 里,最多可以寫入 6 條指令到 instruction queue 里。也就是說:在每個 cycle 里,pre-decoder 最多可以從 16-bytes 里解析出 6 條指令放入 instruction queue。要達到每 cycle 6 條指令,這說明平均每條指令不能超過 2 個字節(jié)。如果這 16 字節(jié)里包含多于 6 條指令(例如每條指令為 2 個字節(jié)),則在下一個 cycle 里 pre-decoder 會繼續(xù)按每 cycle 最多解碼 6 條指令進行解碼。
例如,fetch line(16 字節(jié))里含有 7 條指令,那么首 6 條指令會在一個 cycle 完成解碼寫入 instruciton queue 里,第 7 條指令將在下一個 cycle 里解碼。在下一個 cycle 里,ICache 會繼續(xù)發(fā)送 16 bytes 到 pre-pecoder 里,pre-pecoder 繼續(xù)最多解碼 6 條指令。
指令的 operand size 以及 address size 會影響著指令長度。我們知道 CS.D 決定了指令的 default operation size(默認的操作寬度)。當 CS.D = 1 時,默認的 operand size 與 address size 為 32 位。CS.D = 0 時,默認的 operand size 與 address size 為 16 位。但是,default operand-size override prefix 與 default address-size override prefix 可以改變操作數(shù)與地址的寬度,從而改變了指令固定的長度,這兩個 prefix 被稱為LCP(length changing prefix)。
default operand-size override prefix(66H):重新改寫默認的 32 位或者 16 位 operand size 為 16 位或者 32 位。
例如:mov eax, 11223344h。它的指令編碼為 B8 44 33 22 11(指令長度為 5),當插入 66H 字節(jié)時,指令編碼為 66 B8 44 33(指令長度為 4)。 default address-size override prefix(67H):重新改寫默認的 32 位或者 16 位 address size 為 16 位或者 32 位。
例如:mov eax, [11223344h],它的指令編碼為 A1 44 33 22 11(指令長度為 5),當插入 67H 字節(jié)時,指令編碼為 67 A1 44 33(指令長度為 4)
當然,也可能存在超過 1 個 LCP 的情況(同時存在 66H 與 67H)。因此,如果指令含有 LCP 的話,pre-decoder 需要確定最終的指令長度,在解碼 LCP 時需要額外花費 3 個 cycles (注:在前一代架構(gòu)中,解碼 LCP 需要花費 6 個 cycles)。另外,REX prefix 雖然也能改變指令的長度(MOV reg, [disp32] 或者 MOV reg64, imme64),但 pre-decoder 解碼時并不會花費額外的 cycles。
1.3 instruction queue
instruction queue 組件在 pre-decoder 與 decoder 之間,經(jīng)過 pre-decoder 后指令的長度已經(jīng)確認,從 ICache 傳送過來的 16-bytes 被解析為 x86 指令寫入 instruction queue(指令隊列)里存放著,instruction queue 最多可以容納 18 條指令。由于 macro-fused(宏融合,兩條指令解碼為 1 個 uop)的存在,instruction queue 每個 cycle 最多傳送 5 條指令(其中包括了兩條可以宏融合的指令)到 decoder 進行解碼。
1.4 decoder
decoder 負責將 x86/x64 的 CISC 指令解碼為單一功能的 micro-ops(uops,微操作),從 core 微架構(gòu)開始就擁有 4 個 decoder(解碼器)。第 1 個 decoder(decoder 0) 是復雜解碼器,能解碼所有的 x86/x64 指令,每個 cycle 最多可以解碼為 4 個 uops。其余 3 個為簡單解碼器,將簡單指令解碼為 1 個 uop,每個 cycle 只能解碼 1 個 uop。
第 1 個復雜解碼器也能解碼簡單指令,因此 4 個 decoder 都能解碼為 1 個 uop,包括 micro-fused(微融合),stack pointer tracking(棧指針跟蹤)以及 macro-fused(宏融合)。但是,只有一個 decoder 能解碼為 4 個 uops。那么,4 個 decoder 每個 cycles 最多可以解碼為 7 個 uops(4 + 1 + 1 + 1)。decoder 解碼后的 uops 被送入到 decoded ICache 以及 micro-op queue。
MSROM 組件負責提供復雜的 uops 數(shù)據(jù)流,在 sandy bridge 微架構(gòu)里 MSROM 每個 cycle 能提供 4 個 uops,MSROM 用來幫助 decoder 解碼超過 4 個 uops 的指令。因此,當指令超過 4 個 uops 將從 MSROM 里取得。向 MSROM 取 uops 的操作可以由 decoder 或者 decoded ICache 組件發(fā)起。
通過 macro-fusion(宏融合)技術(shù),decoder 能將兩條 x86 指令解碼為 1 個 uop。4 個 decoder 都可以產(chǎn)生 macro-fused 動作,但在每個 cycle 里 4 個 decoder 只能產(chǎn)生一個 macro-fused。因此,在每個 cycle 里 decoder 最多能解碼 5 條 x86 指令(2 + 1 + 1 + 1),最多能產(chǎn)生 7 個 uops。
1.4.1 micro-fusion(微融合)
x86/x64 指令允許使用“memory-to-register”類操作數(shù),當指令的操作數(shù)是 memory 與 register 時將解碼為多個 uops。例如:“ADD RAX, [RBX]”指令是一條典型的操作數(shù)為 memory 與 register 的指令,它會被解碼為兩個 uops:一個為 load uop,另一個為 add uop。
考查下面的一條 store 操作指令:
mov [rbx + rcx * 8 + 0Ch], rax
---------------------  ---
|               |
|               +--------> store data 操作(使用 port 4)
|
+------------------------> store address 操作(使用 port 2 或 port 3)
decoder 0 生成兩個 uops:一個是 store address 操作 uop,可以通過 port 2 或者 3 執(zhí)行。一個是 store data 操作 uop,通過 port 4 執(zhí)行。但在 dispatch 到 execution unit(執(zhí)行單元)時這兩個單一的 uop 被融合為一個復雜的 uop。
micro-fused(微融合)允許將多個 uops 融合為 1 個復雜的 uop 進行 dispatch 到 execution unit(執(zhí)行單元)。在發(fā)射到執(zhí)行單元時,這個復雜的 uop 與單一的 uop 花費同樣的 cycles。因此,使用 micro-fused 將提高從 decoder 發(fā)射到 execution unit 的吞吐量。但是,在執(zhí)行單元中仍然是執(zhí)行兩個 uops 操作。
從 core 微架構(gòu)開始引入了 micro-fusion 功能,可以將下面幾類操作進行 micro-fused:
store 操作:包括了 sotre 寄存器與立即數(shù)。例如:“mov [rdi], rax”指令與“mov DWORD [rdi], 1”
load-and-operation 操作:指令的操作數(shù)是 register 與 memory,執(zhí)行的是“l(fā)oad + op”操作(被解碼為 load uop 與另一個操作 uop)。
例如:“add rax, [rsi]”,“addps mmx0,[rsi]”,“xor rax, [rsi]”指令等等...
load-and-jump 操作:這是一條分支指令,目標地址從 memory 地址 load 而來。例如:“jmp QWORD [rax]”,“call QWORD [rax]”指令。RET 指令也是屬于 micro-fusion 指令,因為它從 RSP 指向的棧里 load 目標地址(即返回地址)。
memory 與 immediate 之間的 cmp-or-test 操作:CMP 或者 TEST 指令的操作數(shù)是 memory 與 immediate。例如:“cmp DWORD [rsi], 1”,“test DWORD [rsi], 1”指令等。
在 64-bit 模式下,指令使用 RIP-relative 尋址的 memory 時,在下面的情形下不能產(chǎn)生 micro-fused:
指令的另一個操作數(shù)是 immediate。例如:“mov DWORD [rip + 50h], 400”,“cmp QWORD [rip + 50h], 1”指令等。
RIP-relative 尋址出現(xiàn)在分支指令里。例如:“ jmp QWORD [rip + 50h]”指令。
1.4.2 macro-fusion(宏融合)
macro-fused 將兩條 x86 指令融合為一個 uop,允許進行宏融合的兩條指令需要滿足下面條件:
第一條指令修改了 eflags/rflags 寄存器(不同微架構(gòu)所支持的指令也不同)。
core, nehalem 微架構(gòu)上只支持 CMP 與 TEST 指令。
sandy bridge 微架構(gòu)上支持 CMP, TEST, ADD, SUB, AND, INC 以及 DEC 指令。
如果存在兩個操作數(shù)(operand 1 與 operand 2),這些指令能產(chǎn)生 macro-fused 還需要滿足的條件是:operand 1(目標操作數(shù))是 register,并且 operand 2(源操作數(shù))是 immediate,register,或者非 RIP-relative 尋址的 memory。或者 operand 1 是 memory,而 operand 2 是 register。 REG-REG:例如 cmp eax, ecx 指令。
REG-IMM:例如 cmp eax, 1 指令。
REG-MEM:例如 cmp eax, [esi] 指令(非 RIP-relative 尋址)。
MEM-REG:例如 cmp [esi], eax 指令。
但是,MEM-IMM 操作數(shù)不能產(chǎn)生 macro-fused,例如 cmp DWORD [eax], 1 指令。 后面的指令是條件分支指令(Jcc 指令)。但是,不同的指令,以及不同的微架構(gòu)所支持的條件不同。
TEST 指令所有的條件(所有的 eflags 標志位),包括:OF,CF, ZF, SF 以及 PF 標志位。
CMP 指令根據(jù)不同微架構(gòu)支持不同的條件。
core 微架構(gòu)僅支持 CF 與 ZF 標志位。因此,支持下面的 Jcc 指令:
JC/JB/JNAE:CF = 1
JNC/JNB/JAE:CF = 0
JZ/JE:ZF = 1
JNZ/JNE:ZF = 0
JBE/JNA:CF = 1 or ZF = 1
JA/JNBE:CF = 0 and ZF = 0
nehalem 微架構(gòu)增加了對 SF <> OF 與 SF == OF 條件的支持:
JL/JNGE:SF <> OF
JNL/JGE:SF = OF
JLE/JNG:SF <> OF or ZF = 1
JNLE/JG:SF = OF and ZF = 0
sandy bridge 微架構(gòu)增加了對 ADD, SUB, AND, INC 以及 DEC 指令的支持,它支持的條件如下表所示。
條件
分支指令
TEST
AND
CMP
AND
SUB
INC
DEC
OF = 1
JO
Y
Y
N
N
N
N
N
OF = 0
JNO
CF = 1
JC/JB/JNAE
Y
Y
Y
Y
Y
N
N
CF = 0
JNC/JNB/JAE
ZF = 1
JZ/JE
Y
Y
Y
Y
Y
Y
Y
ZF = 0
JNZ/JNE
CF = 1 or ZF = 1
JBE/JNA
Y
Y
Y
Y
Y
N
N
CF = 0 and ZF = 0
JNBE/JA
SF = 1
JS
Y
Y
N
N
N
N
N
SF = 0
JNS
PF = 1
JP/JPE
PF = 0
JNP/JPO
SF <> OF
JL/JNGE
Y
Y
Y
Y
Y
Y
Y
SF = OF
JGE/JNL
SF <> OF or ZF = 1
JLE/JNG
SF = OF and ZF = 0
JG/JNLE
上表中,Y 表示支持宏融合,N 表示不支持宏融合。
在 core 微架構(gòu)里,不支持 signed 數(shù)的比較產(chǎn)生宏融合(即 JL/JNGE, JGE/JNL, JLE/JNG 以及 JG/JNLE)。這個情況在 nehalem 微架構(gòu)里得到改善,支持 signed 數(shù)的比較結(jié)果產(chǎn)生宏融合。
1.4.3 stack pointer tracker
PUSH, POP, CALL, LEAVE 以及 RET 指令會隱式地更新 stack pointer 值,在 core 微架構(gòu)之后 decoder 負責維護這個隱式的更新 stack pointer 操作。
思考一下這條指令 “push rax”,它在以前的微架構(gòu)中會產(chǎn)生多個 uops,大概處理如下面所示:
(1) TEMP = RAX                             ;; ===> renaming ?
(2) RSP = RSP - 8                          ;; ===> 生成 ALU uop
(3) [RSP] = TEMP                           ;; ===> 生成 STA(store address)uop 與 STD(store data)uop
那么,根據(jù)上面的拆分,decoder 大致可以解碼為 3 個 uops:1 個 SUB uop,1 個 STA(store address) uop 以及 1 個 STD(store data) uop。
再來看看這兩條指令“pop rax”與“ret”,大概處理如下面所示:
pop rax :
(1) rax = [RSP]                           ;; ===> 生成 LD uop
(2) RSP = RSP + 8                         ;; ===> 生成 ADD uop
ret :
(1) RIP = [RSP]                           ;; ===> 生成 JMP uop
(2) RSP = RSP + 8                         ;; ===> 生成 ADD uop
pop rax 指令可以解碼為 2 個 uop:1 個 LD(load data) uop 與 1 個 ADD uop。ret 指令可以解碼為 2 個 uop:1 個 JMP uop 與 1 個 ADD uop。
引進 stack pointer tracker (棧指針跟蹤器)這個功能后,將隱式棧指針更新操作移到 decoder 里實現(xiàn),從而釋放了 execution unit(執(zhí)行單元)資源,增加了發(fā)射與執(zhí)行帶寬。PUSH 指令需要 2 個 uops,而 POP 與 RET 只需要 1 個 uop。
1.5 decoded ICache
由于 x86 指令的不定長以及指令解碼 uops 數(shù)量的不同,需要使用 decoded ICache 來緩存從 decoder 里解碼出來的 uops。送入 decoder 進行解碼的 16 bytes 可能會解析出少于 4 條 x86 指條或者多于 4 條(按平均每條指令 4 個 bytes 來算),解碼出來的 uops 數(shù)量也會不同,而 out-of-order 執(zhí)行單元每個 cycle 最多允許執(zhí)行 6 個 uops。造成前端的解碼與后端執(zhí)行的 uops 不匹配,引入 decoded ICache 能很大程度地緩解這些不匹配而帶來的 bandwidth(帶寬)瓶頸。
decoded ICache 是 8-ways 32-sets 結(jié)構(gòu),如下圖所示:
每 set 的每個 way 最多能容納 6 個 uops。因此,理想狀態(tài)下整個 decoded ICache 能緩存 6 * 8 * 32 = 1536 個 uops。
每個 way 裝載的 uops 是由 x86 指令字節(jié)里的 32 bytes 邊界解碼出來的(x86 指令 32 字節(jié)邊界對齊),也就是以 32 bytes 為一個塊,作為裝載單位。
如果 32 bytes 指令塊解碼出來不足 6 個 uops 時,則 way 不會被填滿而留下空位。下一個 32 bytes 指令塊解碼的 uop 會裝入下一個 way 里。
如果 32 bytes 指令塊解碼出來的 uops 超過 6 個時,表明一個 way 不能裝下全部 uops,則余下的 uops 會裝載到下一個 way 里。最多有 3 個連續(xù)的 ways 來容納這些 uops。也就是 32 bytes 的指令塊解碼出來的 uops 最多只能裝入 3 個 ways 里。那么,允許一個 32 bytes 指令塊最多只有 18(6 * 3) 個 uops 可以裝入 decoded ICache 中。
除了上面,way 的裝填還有一些限制:
如果一條 x86 指令解碼為多個 uops 時,這些 uops 不能跨 way 裝載,只能放入同一個 way 里。
每個 way 里最多只能裝入 2 個分支 uops
當指令從 MSROM 里獲得 uops 時,這些 uops 必須獨占一個 way。
非條件分支 uop 必須是 way 里的最后一個 uop。
如果指令含有 64 位的立即數(shù),這個立即數(shù)必須占用兩個 way。
當由于這些限制而造成 uops 不能裝入 decoded ICache 時(例如 32 bytes 指令塊解碼出來可能超過 18 個 uops),這些 uops 被直接發(fā)送到 out-of-order engine。
decoded ICache 是 L1-ICache(instruction cache)和 ITLB 對應(yīng)的一份 shadow cache,ICache 存放的是 x86 指令字節(jié)碼,而 decoded ICache 存放的是 uops。也就是說:decoded ICache 里緩存的任何一個 uops 都在 ICache 里存在著對應(yīng)的 x86 指令。那么,刷新 ICache lines 的指令時,也必須刷新 decoded ICache 里指令對應(yīng) uops。
當 ITLB 的某個 entry(或全部)被刷新時,可能造成整個 ICache 被刷新,同時也會使得整個 decoded ICache 被刷新。例如:更新 CR3 寄存器值從而更新了整個頁轉(zhuǎn)換表結(jié)構(gòu)(或者 CR4 寄存器某些頁機制相關(guān)的控制位被更新)。
1.6 BPU (branch prediction unit)
流水線前端利用 BPU(分支預測單元)盡可能地在確定分支指令的執(zhí)行路徑之前就預測出分支的目標地址。BPU 能預測下面的分支類型:
conditional branches(條件分支):也就是 Jcc 指令族。
test eax, eax
jz @taken
... ...                                 ;; 分支跳轉(zhuǎn)不成立
@taken:
... ...                                 ;; 分支跳轉(zhuǎn)成立
BPU 預測這個分支跳轉(zhuǎn)的目標地址。也就是預測這個跳轉(zhuǎn)是否成立。
direct calls/jumps(直接的調(diào)用與跳轉(zhuǎn)),它們的目標地址是基于 RIP 與 offset 值而來。如下面代碼所示:
jmp @target                             ;; 直接跳轉(zhuǎn)
... ...
@target:
... ...
call @fun                               ;; 直接調(diào)用
indirect calls/jumps(間接的調(diào)用與跳轉(zhuǎn)),它們的目標地址從 register 或 memory 里讀取。如下面代碼所示:
@fun:           __func
... ...
@target:        __target
jmp DWORD [@target]                     ;; 間接跳轉(zhuǎn)
;;
;; 或者:
;;      mov eax, __target
;;      jmp eax
... ...
__target:
... ...
call DWORD [@fun]                       ;; 間接跳轉(zhuǎn)
;;
;; 或者:
;;      mov eax, __func
;;      call eax
returns(調(diào)用返回),也就是 RET 或 RET n 指令。使用 16 個 entries 的 RSB(return stack buffer)結(jié)構(gòu)實現(xiàn)。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
程序的機器級表示
I-Cache與D-Cache
匯編指令
偷懶的BTB ?ARM Cortex X1 初探
dd
UBOOT添加命令的執(zhí)行流程(轉(zhuǎn)載)
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服