討論MIPS 體系和CISC體系結(jié)構(gòu)的不同之處
MIPS(Million Instructions Per Second):單字長定點指令平均執(zhí)行速度 Million Instructions Per Second的縮寫,每秒處理的百萬級的機器語言指令數(shù)。這是衡量CPU速度的一個指標。像是一個Intel 80386 電腦可以每秒處理3百萬到5百萬機器語言指令,即我們可以說80386是3到5MIPS的CPU。MIPS只是衡量CPU性能的指標。MIPS是世界上很流行的一種RISC處理器。MIPS的意思是“無內(nèi)部互鎖流水級的微處理器”(Microprocessor without interlocked piped stages),其機制是盡量利用軟件辦法避免流水線中的數(shù)據(jù)相關(guān)問題。它最早是在80年代初期由斯坦福(Stanford)大學Hennessy教授領(lǐng)導的研究小組研制出來的。MIPS公司的R系列就是在此基礎上開發(fā)的RISC工業(yè)產(chǎn)品的微處理器。這些系列產(chǎn)品為很多計算機公司采用構(gòu)成各種工作站和計算機系統(tǒng)。
一、MIPS指令集的限制
(1)所有指令長度都是32位:這意味著沒有指令能夠僅占用兩三個字節(jié)的內(nèi)存空間(因而MIPS的二進制文件比典型的680x0或80x86大百分之二十到三十),也沒有指令可以超過四個字節(jié)。
隨之而來就是不可能把一個32位常數(shù)放進單個指令中。MIPS設計者決定留出26位常數(shù)的空間用以編碼跳轉(zhuǎn)和調(diào)用指令的目標地址:但是僅有給兩條指令。其它指令只能有16位空間留給常數(shù)。
(2) 指令操作必須適合流水線:只能在相應的流水線階段才能執(zhí)行任務,并且必須在一個時鐘周期內(nèi)完成。例如:寄存器寫回階段只能有一個值存入寄存器堆,所以指令只能修改一個寄存器。
(3)三操作數(shù)的指令:算數(shù)/邏輯指令不需要指定內(nèi)存地址,所以空出了充足的指令位可以定義兩個獨立的源操作數(shù)和一個目的操作數(shù)。編譯器喜歡三操作數(shù)指令,其給了優(yōu)化程序更大的空間來處理復雜的表達式的代碼。
(4)32個寄存器:寄存器數(shù)量的選擇主要是由軟件需求驅(qū)動的,在現(xiàn)代體系結(jié)構(gòu)中一組32個通用寄存器是最為流行的。采用16個肯定不夠現(xiàn)代編譯器的需要,但是32個足夠讓C編譯器把常用的數(shù)據(jù)保存在寄存器中。
(5)寄存器零:$0寄存器永遠返回零,給這個常用的數(shù)提供一個簡縮的編碼。
(6)沒有條件碼:MIPS的指令集的一個特征就是沒有條件標志,這即使在1985年的RISC中也是極為激進的。許多體系結(jié)構(gòu)有多個標志位來表示運算結(jié)果的“進位”、“為零”等等。CISC的典型做法是根據(jù)一些指令的操作結(jié)果設置這些標志,有些RISC體系結(jié)構(gòu)保留了標志位。CISC是復雜指令系統(tǒng)計算機的簡稱,微處理器是臺式計算機系統(tǒng)的基本處理部件,每個微處理器的核心是運行指令的電路。指令由完成任務的多個步驟所組成,把數(shù)值傳送進寄存器或進行相加運算。復雜指令集計算機(Complex Instruction System Computer,CISC)早期的計算機部件比較昂貴,主頻低,運算速度慢。為了提高運算速度,人們不得不將越來越多的復雜指令加入到指令系統(tǒng)中,以提高計算機的處理效率,這就逐步形成復雜指令集計算機體系。為了在有限的指令長度內(nèi)實現(xiàn)更多的指令,人們又設計了操作碼擴展。然后,為了達到操作碼擴展的先決條件——減少地址碼,設計師又發(fā)現(xiàn)了各種尋址方式,如基址尋址、相對尋址等,以最大限度地壓縮地址長度,為操作碼留出空間。
MIPS體系結(jié)構(gòu)決定把所有信息保存到寄存器堆中。比較指令設置通用寄存器,條件分支指令檢測通用寄存器。那樣確實有利于流水線實現(xiàn),因為能夠減少對算術(shù)/邏輯操作依賴的巧妙機制不論從哪一種也都同時會減少比較/分支指令對中的依賴。
我們后邊會看到有效的條件分支意味著是否分支的決定必須在半個流水線周期內(nèi)作出:該體系結(jié)構(gòu)通過保持分支決策的測試條件簡單有助于實現(xiàn)這一點。所以MIPS的條件分支只測試單個寄存器的符號/為零或者一對寄存器是否相等。
二、尋址和訪存
(1)訪問內(nèi)存只能通過簡單的寄存器加載和存儲:對內(nèi)存變量進行算術(shù)運算會打亂流水線。,所以不這么做。每次內(nèi)存訪問都要一條顯式的加載或存儲指令……
(2)只有一種數(shù)據(jù)尋址方式:幾乎所有的加載和存儲都通過單個寄存器基址加上一個16位的常數(shù)偏移量尋址內(nèi)存。
(3)字節(jié)地址指令:一旦數(shù)據(jù)存入MIPS CPU的寄存器,所有的操作都是在整個寄存器上操作。但是象C這樣的語句語義不適合不能尋址內(nèi)存到字節(jié)粒度的機器。因而MIPS對8-和16-位變量提供了一套完整的裝入/存儲操作。
(4)load/store必須對齊:內(nèi)存操作只能從對齊到相應數(shù)據(jù)類型邊界的地址加載荷存儲數(shù)據(jù)。字節(jié)可以在任意地址傳輸,但是半字必須在偶數(shù)地址對齊,字在四字節(jié)邊界對齊。
(5)跳轉(zhuǎn)指令:有限的32為指令長度在想要支持很大程序的體系結(jié)構(gòu)上對分支是個問題。MIPS指令的最小操作碼域為6位,留出了26位來定義跳轉(zhuǎn)的目標。因為所有指令在內(nèi)存中都是四字節(jié)邊界對齊的,低兩位地址無需保存,這樣可有256MB的地址范圍。這個地址不是相對PC的,而是解釋成256MB段內(nèi)的絕對地址。這對大于256MB的單個程序極為不便,到目前按還沒有碰到太大的問題。
超出段內(nèi)的分支可以通過使用一個寄存器跳轉(zhuǎn)指令做到,該指令可以跳轉(zhuǎn)任意32位地址。
條件分支只有16位的偏移域——給出了262144字節(jié)的范圍,因為指令都是四字節(jié)對齊的——解釋成相對PC的帶符號的偏移量。如果知道分支目標會在緊跟分支之后的指令的128KB范圍內(nèi),編譯器就能只生成一個簡單的條件分支指令。
三、MIPS沒有的特性
(1)沒有字節(jié)或半字數(shù)據(jù)的運算:所有算術(shù)和邏輯操作都是在32位的數(shù)據(jù)上進行。字節(jié)或半字的運算需要大量額外的資源和許多額外的操作碼,而且很少有用。
然而當程序明確做short或者char運算時,MIPS編譯器必須插入額外的代碼以保證結(jié)果回繞和溢出,生成跟8-或16-位機器上一樣的結(jié)果。
(2)沒有對堆棧的特殊支持:傳統(tǒng)的MIPS匯編確實定義了一個寄存器作為堆棧指針,但是硬件上SP沒有任何特殊之處。有一種推薦的關(guān)于子程序調(diào)用的棧幀布局,這樣可以混合不同語言和編譯器的模塊;你應當遵守這些約定,但是這些與硬件無關(guān)。
(3)最少的子程序支持:有一點比較特別:跳轉(zhuǎn)指令有一個跳轉(zhuǎn)并鏈接的選項,把返回地址存入一個寄存器,默認是#31.所以方便起見習慣上用#31作為返回地址寄存器。
這樣做比起把返回地址保存到堆棧上要簡單,但卻帶來明顯的好處。隨便舉兩個好處瞧瞧:第一,保持了分支和訪存指令的完全分離;第二,當調(diào)用許多根本不需要在堆棧保存返回地址的小程序時,這樣做又助于提高效率。
(4)最少的中斷處理:很難看到硬件能做得比這更少的了。它把重新開始的地址存放到一個特殊的寄存器,接著僅修改剛剛夠找出怎么回事的少量機器狀態(tài)并禁止進一步中斷,然后跳轉(zhuǎn)到低端內(nèi)存事先定義好的一個單一入口地址,伺候一切由軟件負責。
(5)最少的異常處理:中斷只是異常的一種類型。一個異常可以來自一個中斷,來自對物理上不存在的虛擬內(nèi)存的試圖訪問、或者其它很多情況。一條有意引入的、類似系統(tǒng)調(diào)用的、用來進入受保護的OS內(nèi)核的自陷指令發(fā)生時,也會進入一個異常。所有異常都導致控制傳遞到同樣的固定入口地址。
按照約定,保留了兩個通用寄存器給用于異常,這樣異常處理程序可以自舉。對于運行在允許中斷和自陷的任何系統(tǒng)上的程序來說,這兩個寄存器的值隨時可能變化,所以最好不要用。
四、程序員可見的流水線效果
到目前為止,以上就是你需要從一個簡化的CPU了解的全部內(nèi)容。中央處理器(英文Central Processing Unit,CPU)是一臺計算機的運算核心和控制核心。CPU、內(nèi)部存儲器和輸入/輸出設備是電子計算機三大核心部件。電腦中所有操作都由CPU負責讀取指令,對指令譯碼并執(zhí)行指令的核心部件。其功能主要是解釋計算機指令以及處理計算機軟件中的數(shù)據(jù)。所謂的計算機的可編程性主要是指對CPU的編程。 CPU由運算器、控制器和寄存器及實現(xiàn)它們之間聯(lián)系的數(shù)據(jù)、控制及狀態(tài)的總線構(gòu)成。差不多所有的CPU的運作原理可分為四個階段:提?。‵etch)、解碼(Decode)、執(zhí)行(Execute)和寫回(Writeback)。然而使得指令集適應流水線也會導致一些奇怪的效果。
圖1.3:流水線和分支延遲
(1)延遲分支:MIPS CPU的流水線結(jié)構(gòu)意味著當一個跳轉(zhuǎn)/分支指令到達執(zhí)行階段產(chǎn)生新的程序計數(shù)器值時,跟在跳轉(zhuǎn)指令后的指令已經(jīng)開始了,該體系結(jié)構(gòu)并不是丟棄這部分有潛在用途的工作,而是要求緊跟分支后的指令總是在分支目標指令之前執(zhí)行。MIPS處理器是八十年代中期RISC CPU設計的一大熱點。MIPS是賣的最好的RISC CPU,可以從任何地方,如Sony, Nintendo的游戲機,Cisco的路由器和SGI超級計算機,看見MIPS產(chǎn)品在銷售。目前隨著RISC體系結(jié)構(gòu)遭到x86芯片的競爭,MIPS有可能是起初RISC CPU設計中唯一的一個在本世紀盈利的。和英特爾相比,MIPS的授權(quán)費用比較低,也就為除英特爾外的大多數(shù)芯片廠商所采用。
要是硬件沒有特殊處理,是否分支的決定以及分支的目標地址,就會在ALU流水階段結(jié)束時得到——到此時,如圖1.3所示,已經(jīng)太晚了,甚至在下下一個流水線槽都來不及提供一個指令地址。
但是分支指令的重要性足以給予特殊處理。從圖1.3所示,提供了一條經(jīng)ALU的特殊路徑可以讓分支目標地址提早半個周期到達。連同取指階段多出來的半個時鐘周期的偏移,就剛好來得及去除分支目標指令作為下下一個指令。
編譯器系統(tǒng)或者匯編程序應該考慮甚至利用分支延遲;結(jié)果是通常有可能通過適當安排使得延遲槽中的指令做些有用的工作。經(jīng)??梢园褎e處的指令一道延遲槽中。
對于條件分支問題會有點復雜,分支延遲指令應當對兩條分支路徑都無害。實在找不到有用的事情可做時,延遲槽中填入一條nop指令。除非明確要求,否則許多MIPS匯編器都對程序員隱藏這個古怪的特性。
圖1.4:流水線和加載延遲
(2)數(shù)據(jù)加載延遲:流水線的另一個后果就是一條加載指令的數(shù)據(jù)在下一條指令的ALU階段的開始才從高速緩存/內(nèi)存系統(tǒng)到達——所以在下一條指令中不能使用加載的數(shù)據(jù)。
緊接加載指令后的指令位置稱為加載延遲槽,一個優(yōu)化的編譯器將試圖用它做些有用的事情。匯編器對程序員隱藏這一點,但可能插入一條nop指令。
在現(xiàn)代的MIPS CPU上,加載結(jié)果是互鎖的:如果你試圖過早使用結(jié)果,CPU將停下來等待數(shù)據(jù)到達。但是早期的MIPS CPU沒有互鎖,在延遲槽中試圖使用數(shù)據(jù)將導致無法預料的結(jié)果。
QICK