題:
ISA操作碼-它們來自哪裡?
Steven
2017-09-05 12:06:59 UTC
view on stackexchange narkive permalink

工程師在設計指令集體系結構時,在將某些二進制代碼指定為指令時會遵循什麼程序或協議(如果有)。例如,如果我有一條說10110是加載指令的ISA,那麼二進制數字從何而來?是否從狀態表中為表示加載操作的有限狀態機建模?

編輯: 經過更多研究之後,我相信我要問的問題與如何分配各種CPU指令的操作碼有關。可以使用10011的操作碼來指定ADD;一條加載指令可能指定為10110。為指令集分配這些二進制操作碼有什麼思路?

Monte Dalrymple的“使用Verilog HDL進行微處理器設計”為Z80 CPU提供了非常詳細的設計方法,從中我想您會學到很多有關您的問題的知識。但是,有許多考慮因素需要進入特定的選擇,包括對其他指令集的統計分析,編譯器輸出等。不過,我還是建議從該書開始。儘管它以已知的設計開始,但他深入了解了它,我想您會學到一些東西。好書。
或者,也許您是在詢問執行引擎的設計,並且想知道指令中的位會如何發揮作用?從您的措辭不確定。
有人問這個問題。必須是星期二。
什麼是ISA?
指令集架構。
@Steven考慮一下。如果*您*必須設計一個ISA,那麼*您*會怎麼想?如果您的指令長度不盡相同,那麼*您*將如何選擇較短或較長的指令字,針對哪些指令?如果您必須設計一個*解碼階段*,那麼您的ISA希望*看起來像什麼?我認為這個問題是不必要的廣泛問題(因此幾乎不可能完全回答),但是您可以通過添加一些自己的想法並提出一個不需要我們寫書的“精確”問題來進行很多改進回答它。
[RISC-V規範](https://riscv.org/specifications/)討論了他們在各個級別上做出的設計決策,其中包括有關機器指令編碼的一些知識。(這對於處理器手冊來說是不尋常的;與大多數人不同,RISC-V首先是學術練習,其次是CPU體系結構。)
要查看10k-30k的俯視圖,請查閱charles petzold撰寫的Code
七 答案:
Brian Drummond
2017-09-05 14:48:29 UTC
view on stackexchange narkive permalink

這取決於ISA的年齡。

在手工設計的早期,甚​​至更進一步地,當從離散邏輯組裝CPU時,邏輯設計將首先出現並被大大減小,然後ISA位模式將成為需要的任何值。使最小的邏輯工作。

因此,可能存在使某些多路復用器能夠將ALU輸出連接到GP寄存器文件的輸入的控制信號的特定模式,還有一些指示ALU加,減,AND,OR等的控制信號,和一些地址位到寄存器文件中。這三組信號將在指令內形成字段。每個組將保持在一起,其詳細含義從該單元(ALU等)的設計中產生,但是直到您設計指令解碼器之前,這些組可以以任何順序排列。 (x86足夠舊,如果您在正確的位置查看,您可以檢測到其中的某些部分-它不是全新設計,而是藉鑑了較舊的8080)

以後的ISA可能會被“清理”並變得更加常規和易於使用,並且硬件有時會通過“微碼”在它們和實際的硬件級控制信號之間進行轉換。這些被稱為“ CISC”或“複雜指令集編碼”。 x86“ Rep”指令前綴就是一個簡單的例子-它使以下指令重複多次,從而省去了編寫FOR循環的麻煩。

後來(在1980年代)又回到了一種簡單的直接編碼樣式(RISC-精簡指令集編碼),您可以在ARM處理器中看到這種樣式。這是由於當時的ASIC尺寸較小,並且希望在其上放置32位CPU,因此復雜的指令集解碼器沒有多餘的容量,無法將整個CPU降低到大約20,000門。(這也是暫時的性能提升,因為人們還沒有開發出使CISC解碼器更快的技術-大約在1995年,奔騰Pro就出現了)

如今,這無關緊要-CPU一次讀取幾條指令,並投入數百萬個晶體管對其進行解碼,重新排序並一次執行盡可能多的指令,以加速可能已編寫的程序最古老的ISA。

我不確定我是否真的將CISC稱為“更易於使用”。那可能是最初的意圖,但是30年後,它們有點像“易於使用”(至少與RISC ISA相比)。
從某些方面來說,它們更易於使用...早在編譯器是相對瑣碎的程序時就可以使用正則性(正交性是一個大話題),或者可以直接支持更高級別的操作,從而減少編譯器的翻譯。但這是很久以前的事了,任何尚存的CISC都在其原始指令集的基礎上進行瞭如此多的修訂。編譯器也已經改變了所有的認識-那時gcc執行的大約1000次優化遍歷是不可想像的。因此,當時和現在幾乎沒有什麼關係。
這種區別既被侵蝕(添加更多指令的“ RISC”集),又被新的甚至更複雜的體系結構(例如VLIW)所取代;真正唯一的共識是x86(16位和32位)很難使用
如這裡所建議的,微碼是屬性還是CISC處理器的主要屬性?
@tonysdg:很難使用RISC,也很難使用CISC。“程序員友好性”的一個很好比較是比較68k與ARM。ARM是為編譯器設計的,因此您必須進行大量手動工作才能從RAM中獲取數據並將其寫回RAM。68k是為彙編程序員設計的,可讓您直接對RAM中的數據進行操作。如果您查看68k ISA,您會發現它看起來很像現代RISC ISA,但有一個例外-您可以直接在RAM上進行操作,而RISC僅允許您在寄存器上進行操作。
微碼主要是CISC屬性。但是,您可以在沒有微代碼的情況下實現CISC:指令解碼器會更複雜。您還將看到從Pentium-Pro開始的一些CISC在內部被描述為RISC。將每條CISC指令轉換為一個或多個內部RISC操作:微碼的另一種名稱(儘管在超標量執行單元中區別變得模糊)
-1
@Luaan是什麼意思,它比CISC指令慢多少?
@Ruslan在第一個Pentium中,甚至直接使用內存操作數進行算術的速度仍然較慢。例如`cmp reg,mem`的周期是`mov reg,mem'的兩倍;cmp reg,reg`。add mem,reg的速度可能是中間寄存器的三倍。更糟糕的是更複雜的指令,例如xchg,xlat或enter / leave。當然,這對您的代碼有多大影響還取決於許多其他因素:)它們都可以用等效的RISC代碼替換,這些代碼更快,通常更具可伸縮性(儘管如果您無法保留寄存器,則可能會改變)。
@Luaan嗯,你說x86-64修復了這個問題,但是所有這些指令仍然以本機64位模式出現,與諸如`aad`,`bound`,`das`,`into`等類似。
pjc50
2017-09-05 14:15:39 UTC
view on stackexchange narkive permalink

如果將相似的指令組合在一起,則會出現模式。這在ARM中非常明顯,ISA手冊實際上向您顯示了指令字的哪一位對應於功能,寄存器選擇等。但是也可以從 X86推論得出。

最終,操作碼的“功能”部分進入某種二進製到單字節的解碼器,該解碼器實際上激活了特定功能或流水線操作序列。它們通常與任何狀態機的內容都不相關,除非我們考慮使用需要狀態機進行解碼的變長指令。

您基本上是在說他們正在爭取芯片上盡可能少的晶體管數量。我完全同意OP的問題,因為他們無法負擔得起數百個額外晶體管的整潔指令集。上百萬個晶體管的CPU沒有太多需要理會的理由,但是當然有許多理由保留它是為了向後兼容。
@Harper仍然是有原因的,因為儘管晶體管變小了,但它們仍然具有尺寸-同時時鐘速率也增加了很多。因此,太大的指令解碼器仍然會成為性能的瓶頸(許多CPU提前選擇“預*”解碼指令的原因之一)。這與晶體管數量無關,而與時鐘速率和芯片面積有關。信息仍然需要花費時間來傳播,並且儘管現代CPU並沒有以光速運行,但距離速度極限還遠遠不夠,無法期待顯著的改進。
@Luaan:實際上,“如今我們如何處理所有這些晶體管”是一個真正的問題。看一下當今拋出的所有L2 / L3緩存。這是一個無聲的承認,我們沒有更好地使用所有數百萬個晶體管。最新的Xeon專用緩存超過2十億個晶體管!
ratchet freak
2017-09-05 14:33:27 UTC
view on stackexchange narkive permalink

某人坐下來對它們進行了定義。

良好的ISA將使解碼器盡可能簡單。

例如,使用ALU指令,您可以讓操作碼的某些位直接發送到ALU的控制線中。

感謝所有人的出色回答。你們都幫助我更好地理解了這一點。
實際上,除了解碼器的簡便性之外,還有很多其他因素需要考慮。取決於環境和預期用途,其他因素(例如,代碼密度)可能比解碼器簡單性更為重要。在現代處理器中,在大多數情況下,代碼密度可能超過解碼器的簡便性。
Artelius
2017-09-06 17:42:30 UTC
view on stackexchange narkive permalink

在許多情況下,隨著ISA的增長,選擇是相當隨意的,或者基於“最合適的位置”。但是,MOS 6502是芯片的一個很好的例子,在該芯片中,嘗試從有限的晶體管中盡可能多地擠壓ISA設計受到了很大的影響。

觀看這段視頻,特別是從34:20開始,解釋6502是如何反向工程的

6502是1975年推出的8位微處理器。儘管它的閘門數量比Z80少60%,但速度卻是Z80的兩倍,儘管它受到更多限制(在寄存器等方面),但它彌補了帶有精美的指令集。

它僅包含3510個晶體管,這是由一小群人用手工拉出的,它們是由一小群人爬過一些大的塑料板,這些塑料板隨後被光學收縮,從而形成了6502的各個層

如下所示,6502將指令操作碼和時序數據傳遞到解碼ROM,然後將其傳遞到“隨機控制邏輯”組件,其目的可能是在某些複雜情況下否決ROM的輸出。

6502 block diagram

在視頻中的37:00,您可以看到解碼ROM的表,該表顯示輸入必須滿足哪些條件才能為給定的控制輸出獲得“ 1”。您也可以在此頁面上找到它。

您可以看到此表中的大多數內容在各個位置都有X。讓我們舉個例子吧

  011XXXXX 2 X RORRORA
 

這意味著操作碼的前3位必須為011,G必須為2;別的都無所謂。如果是這樣,則名為RORRORA的輸出將為true。所有ROR操作碼均以011開頭;但是還有其他說明也以011開頭。這些可能需要由“隨機控制邏輯”單元過濾掉。

因此,基本上,選擇了操作碼,以便需要彼此執行相同操作的指令在其位模式中具有某些共同點。您可以通過查看操作碼表來查看此內容;所有“或”指令均以000開頭,所有“存儲”指令均以010開頭,所有使用零頁尋址的指令的格式均為xxxx01xx。當然,某些指令似乎並不“合適”,因為其目的不是要具有完全規則的操作碼格式,而是要提供功能強大的指令集。這就是為什麼需要“隨機控制邏輯”的原因。

我在上面提到的頁面上說,ROM中的某些輸出行出現了兩次,“我們認為這樣做是因為它們無法將所需的某些行的輸出路由,所以他們將同一行在另一個位置。”我可以想像工程師們一個接一個地繪製這些門,然後突然意識到設計中的缺陷,並試圖提出一種避免重新啟動整個過程的方法。

Sean Houlihane
2017-09-05 14:04:09 UTC
view on stackexchange narkive permalink

通常,您會將ISA分為功能組。(對於邏輯優化或整潔而言)有意義的是,互補對通過單個位更改(加載與存儲)來區分,並且您具有影響解碼決策樹的某些位層次結構。

最終,為功能塊分配任意位(與在指令中放置“數據”字段相反)只會對總體設計效率產生很小的影響-但您有很多選擇有關如何根據您的感受來“優化” ISA編碼的重要參數。

Peter Green
2017-09-06 16:35:35 UTC
view on stackexchange narkive permalink

指令編碼之間很難兼顧。

使解碼變得簡單,為此,您需要一組簡單的字段,每個字段可以分別解碼,然後路由到執行引擎的單獨部分。

將盡可能多的功能打包到有限大小的指令字中。這就導致了諸如特殊的常量格式之類的事情,該格式可以對各種通用數字進行編碼。

向前和向後兼容性。如果將功能分配給所有可能的操作碼,那麼您將沒有空間擴展以後的體系結構。如果要添加到現有體系結構,則必須將新指令放入備用操作碼中。

DevSolar
2017-09-06 19:05:39 UTC
view on stackexchange narkive permalink

蘭迪·海德(Randy Hyde)出色的著作(如果有些過時了)彙編的藝術 3.3.4控制單元和指令集和正在關注。

早期(馮·諾依曼之前)計算機系統中的程序通常“硬連線”到電路中。也就是說,計算機的佈線確定了計算機將要解決的問題。為了更改程序,必須重新佈線。一項非常艱鉅的任務。計算機設計的下一個進步是可編程計算機系統,它使計算機程序員可以使用一系列插座和插頭線輕鬆地“重新佈線”計算機系統。一個計算機程序由一組行的孔(插槽)組成,每行代表程序執行期間的一個操作。程序員可以通過將電線插入所需的指令的特定插座中來選擇多個指令之一。

然後,他演示了相當吸引人的內容,並詳細演示了前幾對插件代表指令的方式,接下來的插件對源和目標進行編碼。當然,今天沒有人再“插入”了,但是對於真正的ISA來說,操作碼中的位基本上與以前的插入工作相同。

您最終得到這樣的東西:

enter image description here

感謝您從海德獲得的鏈接!這非常有用,他似乎具有出色的教學風格。


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...