專利名稱:終極管道和最優重排技術的制作方法
技術領域:
本發明涉及一種二進制代碼轉換器,該代碼轉換器用于將遺留處理器的二進制代碼直接轉換為本機處理器可執行的二進制代碼,并且更加具體地講,涉及一種形成為可重新配置的代碼轉換器的二進制代碼轉換器,這適合于用于不同的遺留處理器和/或操作系統以及不同的本機處理器,在該轉換器中可對遺留代碼進行靜態轉換、動態轉換或即時轉換,并且允許插入新的代碼或禁用部分遺留代碼,而不對遺留二進制代碼進行修改。
背景技術:
我們都知道,微處理器是利用不同的指令系統體系結構(ISA)配置的。ISA為具體的微處理器確定了指令系統。由微處理器執行的應用程序通常是用稱作源代碼的相對高級語言寫成的,例如用C或C++,并將這些應用程序編譯為與具體的微處理器的指令系統相符的機器指令。這些機器指令稱為二進制代碼、目標碼和可執行代碼。
歸因于許多現有微處理器的老化和陳舊以及它們相應的低速度,經常需要用更新更快的微處理器(這里稱為“本機微處理器”或“本機處理器”)來更換過時的現有微處理器(下文中稱為“遺留微處理器”和“遺留處理器”)。可惜,依靠于升級,本機處理器的指令系統時常與遺留處理器的指令系統不兼容。同樣地,已經開發出了多種多樣的使針對遺留處理器編寫的應用程序能夠在更新的本機處理器上應用的技術。例如,我們已經知道的軟件仿真程序。這種軟件仿真程序是建立在對應用程序中所使用的遺留處理器的各種機器代碼指令進行仿真的基礎上的。我們知道這樣的仿真器包括多個由一個或多個本機指令組成以實現與所仿真的遺留指令相同的功能的軟件處理程序。在共同擁有的美國專利第6041402號、第6212614號和第6272453號以及2003年3月6日申請(摘要第20-0169號)的名稱為《直接指令翻譯仿真計算機技術(Direct Instruction Rendering Emulation ComputerTechnique)》的共同擁有的美國專利申請序列號第__號中,公開了這樣的指令仿真程序系統的實例。
還有一些原因表明了為什么需要二進制代碼轉換器。首先,可能無法利用遺留源代碼向現代計算機體系結構實現軟件移植。其次,與傳統的仿真系統相關的軟件系統開銷顯著地減緩了處理速度。于是,對于遺留代碼在更新的、不兼容的硬件平臺上的再使用來說,二進制代碼轉換是唯一可行的選擇。
這種二進制代碼轉換器將遺留處理器的二進制代碼直接轉換為本機處理器的二進制代碼。在美國專利第6223339號、第6314560號和第6502237號中公開了這種二進制代碼轉換器的例子。而且在于1997年2月23日-26日在加利福尼亞圣何塞召開的97年計算機會議論文集(Compcon’97 proceedings,IEEE)中的第37-42頁的由數字設備公司(Digital Equipment Corporation)的R.Hookway所著的《在Alpha NT上運行32位x86應用程序的DIGITAL FX!32(DIGITAL FX!32 Runningon 32-bit x86 Application on Alpha NT)》、2001年11月出版的IEEE學報第11期第89卷第1710-1722頁中的Altman等人所著的《二進制代碼轉換及優化進展與未來前景(Advances and Future Chanllenges inBinary Translation and Optimization)》、數字技術雜志(Digital TechnicalJournal)1997年第1期第9卷第1-12頁中的由Hookway等人所著的《數字FX!32仿真與二進制代碼轉換的結合(Digital FX!32CombiningEmulation and Binary Translation)》、計算機雜志(Computer Magazine)2000年3月第33卷第47-52頁上的由Zheng等人所著的《PA-RISC到IA-64透明執行,無需再編譯(PA-RISC to IA-64TransparentExecution,No Recompilation)》這些文獻中也公開了二進制代碼轉換器。
雖然已知的二進制代碼轉換器能夠將遺留二進制代碼有效地轉換為本機二進制代碼而無需修改遺留二進制代碼,但是卻存在著與這些已知的二進制代碼轉換器相關的問題。例如,絕大多數二進制代碼轉換器都是為單一的遺留/本機處理器和操作系統的組合而開發的。因此,在不同的遺留處理器和/或本機處理器上運行的應用程序將需要單獨的代碼轉換器。此外,這些已知代碼轉換器不允許為了實現禁用部分遺留代碼或無需重新編譯程序地對其進行增強的目的而添加用現代程序設計語言編寫的新本機代碼,這要求有權使用原始源代碼。因此,存在著對適用于多種遺留處理器和本機處理器和/或操作系統并且在遺留和本機指令層面上都可以進行模塊化優化同時允許無需重新編譯遺留程序地添加新的本機代碼的一種用于將遺留二進制指令轉換為本機指令的二進制代碼轉換器的需求。
發明內容
本發明涉及一種用于將針對遺留處理器編寫的二進制指令直接轉換為本機處理器可執行的二進制指令的二進制代碼轉換器。按照本發明的一個重要方面,所述二進制代碼轉換器是一種可重新配置的代碼轉換器,這使得該二進制代碼轉換器能夠用于遺留處理器和/或操作系統以及本機處理器的不同組合。還對該二進制代碼轉換器進行優化,以利用更有效的本機處理器指令和可用功能,并允許禁用部分遺留二進制代碼和/或將新的本機指令加入到應用程序中而無需改變遺留二進制代碼。
參照后面的說明和所附的附圖,將會更加容易地理解本發明的這些和其它的優點,其中附圖1是一個示范性軟件模型的框圖,它說明了應用程序是如何與系統操作系統和處理器相互作用的。
附圖2是一個框圖,它說明了按照本發明的一個方面的用于將二進制指令插入到本機指令組中的thunk過程。
附圖3是按照本發明的二進制代碼轉換器的框圖,對其各個子系統進行了說明。
附圖4是為了在運行Linux操作系統的本機Intel IA-64處理器上使用而用于對針對Tru64 Unix操作系統編寫的示范性遺留Alpha 21264微處理器應用程序進行轉換的示范性載入程序程序表。
附圖5是表示示范性遺留代碼段和向量空間之間的關系的示范性存儲器分配圖。
附圖6是表示用于按照本發明的二進制代碼轉換器的存儲器配置的示范性示意圖。
附圖7是用于按照本發明的二進制代碼轉換器的類圖。
附圖8是用于按照本發明的二進制代碼轉換器的分級類圖。
附圖9是按照本發明的二進制代碼轉換器的過程圖。
附圖10是按照本發明的用于IA-64微處理器的調度優化程序的框圖。
附圖11是按照本發明的示范性指令調度優化程序算法的流程圖。
附圖12是表示Alpha遺留二進制指令到Intel IA-64本機處理器二進制指令的示范性指令轉換的框圖。
附圖13表示用于Intel IA-64本機處理器的指令束格式。
附圖14表示一個標準型Itanium 2處理器的執行單元格式。
附圖15表示如何將兩個IA-64指令組中的第一個中的經轉換的IA-64本機處理器指令組織為IA-64指令束。
附圖16與附圖15相類似,只是表示對兩個IA-64指令組中的第二個的處理過程。
附圖17表示按照本發明的轉移判定優化方法實例。
具體實施例方式
本發明涉及一種形成為可重新配置的代碼轉換器的二進制代碼轉換器,該代碼轉換器能夠將遺留微處理器的二進制指令直接轉換為本機處理器的二進制指令。遺留處理器的二進制指令的直接轉換得到本機二進制指令,這樣通常要比對遺留指令進行仿真執行起來快得多。此外,依照本發明的一個重要方面,能夠對該系統進行配置以應用于多種本機處理器、多種遺留處理器和操作系統。為了進一步提高經轉換的本機程序的適應性,可以使用thunk對象來禁用部分遺留二進制指令和/或插入新的本機指令而無需改變原始的遺留二進制代碼。如后面將要詳細討論的,按照本發明的二進制代碼轉換器是這樣將遺留二進制代碼轉換為本機二進制指令的首先將遺留二進制指令分組為連續執行的代碼段、實施算法優化,然后將這些二進制指令一條一條地轉換為本機指令系統。一旦完成了指令轉換,如果需要的話,還可以執行本機優化程序。取決于本機處理器,可以對本機二進制指令進行重排和/或分組,以充分利用可用的處理器資源。所得到的本機二進制指令因此能夠在本機平臺上獨立執行。
按照本發明的二進制代碼轉換器是以三種不同的工作模式進行工作的靜態轉換模式,在該模式下,脫機地完成轉換以生成新的可執行本機指令的二進制代碼;動態轉換模式,在該模式下,轉換是在將遺留二進制代碼載入本機處理器存儲器中的同時進行的;還有一種即時轉換模式,在該模式下,當且僅當首次執行遺留指令需要對他們進行轉換的時候才對這些遺留二進制指令進行轉換。
雖然將按照本發明的二進制代碼轉換器形成為可重新配置的代碼轉換器,其可以為了用于各種遺留的和本機的處理器而進行配置,但是本發明的示范性實施例是一個使用Tru64 Unix操作系統的Alpha21264微處理器和一個使用Linux操作系統的Intel IA-64本機處理器。該Alpha 21264微處理器是一個精簡指令系統計算機(RISC)。使用RISC體系結構配置的微處理器一般在寄存器中執行所有的指令。載入和存儲指令用于將數據取入寄存器和將結果保存回存儲器中。出于這一原因,RISC體系結構被稱為“載入/存儲”體系結構。RISC體系結構還排除了復雜的指令,以降低硬件的復雜程度。現代軟件設計模式促進了高級語言的使用并且編譯器一般不使用復雜的指令。
所述Intel IA-64微處理器采用了一種相對較新的設計模式,稱為顯性并行指令計算機(EPIC)。這種EPIC體系結構規定用于最佳性能的調度指令是由編譯器(或匯編語言編程器)完成的,而不是微處理器硬件。IA-64采用了一些功能部件來消除或減小處理器性能問題的范圍。例如,這種IA-64處理器包含有相對較大的寄存器組;消除短正向轉移的能力;以及相對較大的執行單元數量,以提高并行代碼執行能力。該IA-64微處理器包括一個不斷壯大的微處理器家族。下面的說明涉及一種稱為Itanium 2的標準型IA-64處理器。
應用軟件模型參照附圖1,示出了一個現代軟件應用系統的層次模型。該模型包括一個應用軟件層20、一個系統程序庫層22、一個操作系統層24和一個硬件層26。現代軟件應用系統程序20通常是為了在特定的微處理器體系結構和操作系統上運行而編寫的。如圖所示,應用軟件20利用微處理器操作系統24的服務程序以及一組系統程序庫22來執行通用任務。具體來說,該應用軟件可以直接請求操作系統調用,如箭頭28所示,不過更一般地是借助系統程序庫調用與系統程序庫22進行聯系,如箭頭30所示。順次地,系統程序庫22典型地向操作系統層24請求系統調用,如箭頭32所示。例如,標準C/C++系統程序庫層22包含利用C函數處理磁盤文件的能力。這些函數依次地通過系統調用與操作系統相互作用。如下面將要詳細討論的,按照本發明的二進制代碼轉換器與底層操作系統發生聯系而不需要與遺留和本機操作系統發生聯系。
二進制代碼轉換器子系統參照附圖3,按照本發明的二進制代碼轉換器是由四個模塊化的且可重新配置的子系統組成的一個裝入程序子系統34、一個遺留指令處理程序子系統36、指令轉換器子系統38和一個本機指令處理程序子系統40。每個子系統34、36、38和40都是例如用C++寫成的模塊化對象。照此,任何一個子系統34、36、38和40都可以圍繞一個具體的本機處理器體系結構、一個遺留處理器體系結構或者二者全部來進行設計。照此,按照本發明的二進制代碼轉換器是可重新配置的,就是說它可針對任何遺留的或本機處理器而進行配置,而不象公知的二進制代碼轉換器那樣是針對一個具體的遺留/本機處理器組合而配置的。
后面將給出每個子系統的詳細討論。不過,總地來說,所述載入程序34從遺留二進制文件中讀取遺留代碼和數據段。所述遺留指令處理程序子系統36對這些遺留指令加以分類并將遺留程序分解為遺留進程。此外,如果存在任何轉換前優化模塊并且它們是有效的,那么將會對它們進行調用。所述指令轉換器子系統38將那些遺留指令轉換為本機指令。所述本機指令處理程序子系統40調用轉換后優化模塊,如果有這樣的模塊的話,并將所得到的完全轉換的程序寫入本機處理器存儲器或磁盤文件中,以進行后續運行。
按照本發明的二進制代碼轉換器另外還允許將代碼優化模塊插入到子系統36或40中,以進一步提高系統性能。參照附圖9,這些模塊由附圖標記64和66標示。可以存在任意數量的優化模塊,它們可以對轉換前遺留代碼、轉換后遺留代碼或它們的某種組合進行操作。如果需要,也可以除去這些優化模塊。
按照本發明的二進制代碼轉換器還考慮到了將新的本機代碼插入到轉換后的遺留代碼流中。這些新的本機代碼字段稱為“thunk”。附圖2中示出了一個thunk 42。這些thunk對象42可用于為了實現各種目的而增加功能,而無需改變已有的二進制代碼,例如增加新的功能或禁用部分原始的遺留代碼。如附圖2所示,示出了三個本機指令組塊44、46和48。Thunk代碼是借助從本機指令代碼44指向thunk對象42的向量插入的。執行thunk對象42中的thunk代碼。一旦完成了thunk代碼的執行,如附圖2所示,系統引導返回到本機指令組。
載入程序子系統如上面所提到的,所述載入程序子系統34讀取遺留二進制文件并提取遺留代碼和數據段。該載入程序子系統34是一個可插入系統,它能夠適用于多種文件格式。對于上面所提到的示范性遺留處理器和操作系統來說,示范性的載入程序包括Linux可執行和連接格式(ELF)和Tru64 Unix公用對象文件格式(COFF)。
所述載入程序子系統34僅通過少數幾個接口程序與二進制代碼轉換器的平衡進行聯系。附圖4表示在對使用Tru64操作系統的Alpha遺留微處理器的指令到使用Linux操作系統的Intel IA-64微處理器的轉換中所使用的一個示范性的通用建模語言(UML)程序表。
遺留指令處理程序子系統所述遺留指令處理程序子系統36對遺留指令進行分析、按照它們的一般職能確定它們的類型并將這些指令分解為遺留代碼的功能塊。在遺留指令處理程序子系統36失去控制權之前,它能夠調用任何所需的可用的且有活性的遺留優化程序。遺留指令處理程序子系統36獨立于運行著系統的本機處理器。
遺留指令處理程序子系統36將遺留程序分解為多個段,稱為遺留進程。一個遺留進程是一段以遺留流程控制指令結束的遺留指令,例如轉移指令。每個遺留指令被放置在一個container對象中,稱為“LegacyInstruction”。該LegacyInstruction對象保存在“LegacyProcedure”對象中。如后面將要詳細討論的,在靠后的階段中,將把“NativeInstruction”添加到LegacyProcedure對象中。
每個LegacyInstruction對象含有遺留二進制指令以及關于該指令的信息,該信息包括其總體類型以及如何將其轉換為本機處理器指令。然后container對象可用于在轉換和優化中所使用的其它子系統。所有的遺留進程對象都包含在一個LegacyProgram對象中。
遺留指令處理程序36是一個模塊化子系統并且將其配置得與不同的遺留處理器實現兼容。這可以通過C++對象定向技術來實現。存在基本類以定義所需的接口程序。
在對遺留指令進行了分組和確定了類型之后,遺留處理程序子系統36在退出之前調用任意所需的轉換前優化模塊并且有許多的優化模塊可供選擇執行。轉換前優化模塊對遺留指令起作用并且可以禁用它們,擴充它們,或者與轉換后優化程序相結合產生更好的執行代碼。
指令轉換器子系統所述指令轉換器子系統38進行從遺留處理器指令到本機處理器指令的轉換。該子系統38依賴于遺留和本機處理器體系結構。該子系統38是由其它子系統進行調用的,并且含有執行如下所述的兩個主要功能的指令轉換對象●指令類型確定。遺留指令處理程序36使用指令類型確定判定遺留指令的類型。這種結構方式指示遺留指令處理程序此時它遇到了一個遺留流程控制指令并且提供轉換前優化程序可能需要的類型信息。
●指令轉換。本機指令處理程序子系統36使用這一服務來產生執行遺留指令所要求的操作的本機處理器指令。
所述指令轉換器子系統38最終負責執行所有的遺留到本機的指令轉換。
在本發明的一個示范性的實施例中,其中將Alpha遺留微處理器的二進制指令轉換為用于Intel IA-64微處理器的適當的二進制指令,該指令轉換器子系統38可以由一系列的C函數實現-每一個函數對應于各個Alpha遺留指令來產生所需的IA-64本機處理器指令。這些C函數此后稱為遺留指令轉換器。另外,一系列的C函數,每一個函數對應于一個所需的IA-64遺留本機處理器指令,可以從所述遺留指令轉換器內部使用。這些C函數下文中稱為本機指令發生器。
本機指令處理程序子系統所述本機指令處理程序子系統40請求遺留指令到本機指令的轉換、調用任何需要的本機指令優化模塊并將經轉換的二進制代碼寫入到本機處理器存儲器或一個文件中以備今后使用。
本機指令對象用于保存重復遺留進程的行為所需的本機指令。一個遺留進程所需的本機指令對象的數量可以與或不與遺留指令對象的數量相匹配,這是因為重復遺留指令的行為所需的本機指令的數量是變化的。所有的本機指令對象,作為一個整體,是經轉換的二進制程序的指令部分。
本機指令處理程序子系統40完全可配置為能夠使遺留二進制指令在各種各樣不同的本機處理器上執行的子系統。這個子系統40獨立于正在使用的遺留處理器工作。
如前面所提到的,借助指令轉換器子系統38進行的指令轉換是由本機指令處理程序子系統40調用的。這一過程包括將一定數量的本機指令對象加入到已經產生的遺留進程對象中,這些本機指令對象含有經轉換的主處理器指令。此時本機指令沒有提交給存儲器或文件,這是因為轉換后優化程序可能會改變本機指令組合。
在每個遺留指令都已經轉換為一個或多個本機處理器指令之后,將調用所存在的任意轉換后優化程序。這些可插入模塊可能是激活的或停用的。
轉換過程如上面所提到的,將遺留程序分解為由遺留流程控制指令結束的遺留進程。這允許同時對多個指令進行處理,以得到較佳優化的代碼。例如,Intel IA-64體系結構每時鐘周期允許執行多達六條指令。同時處理多個指令允許根據數據相關性判斷哪些指令對于并行執行是安全的。結果,為遺留指令字段或進程生成的那些本機指令可以不執行與遺留處理器順序完全相同的操作。不過,只要考慮到了數據相關性,這就并不成其為問題了。然而,一次一條地執行Intel IA-64指令,是無法充分利用該處理器的運行資源的。
按照本發明的二進制代碼轉換器使用一個向量表或向量空間,其含有與每條遺留指令相對應的64位值。這些64位值是用于每條指令的本機指令處理程序的完整地址。不過,并不是每條指令都含有一個有效的向量條目,這是由于遺留指令均被分解為以遺留流程控制指令結束的遺留代碼字段。由于按照本發明的二進制代碼轉換器是以連續執行遺留代碼塊或字段的方式工作的,因此僅僅每個相應的遺留代碼字段(或遺留進程)的開端需要一個向量。該向量就是用于某個進程的本機指令處理程序的地址。例如,附圖5表示由附圖標記50和52標出的兩組遺留指令及其地址。每組指令50、52以一個轉移指令BEQ結束,它們組成了一個遺留代碼字段(或遺留進程)。每個遺留地址在所述向量空間中具有一個相應的位置。依次地,每個在所述向量空間中占有一席之地的條目都指向微碼空間中的一個本機指令處理程序。按照本發明的一個方面,在處理轉移指令的時候,二進制代碼轉換器使用一個雙處理周期轉換系統。更具體地講,對于許多遺留轉移指令來說,直接從遺留代碼中確定轉移目的地是可能的。而另外一些情況下,目的地代碼是無法直接確定的。按照本發明的二進制代碼轉換器對這兩種情況均能處理。
轉換的第一個處理周期為所有遺留指令產生本機指令,只是除了跳轉或轉移指令(即流程控制指令)。一旦完成了第一個處理周期,就可以完成相關的轉移指令的轉換了,這是由于其余的代碼都已經產生了。第二個處理周期為那些目的地可以在轉換的時候得到確定的轉移填補轉移指令。
如果可以在轉換的時候確定轉移目的地并且該轉移指向一個沒有有效向量的位置的話,則產生一個LegacyProcedure對象并從那一點開始向前裝入遺留指令直到找到遺留流程控制指令。例如,參照附圖5,如果一個已結束的轉移轉到位置1020,則將會產生一個LegacyProcedure對象并且該對象會為位于地址1020、1024和1028的指令進行轉換。這一處理是在第二個處理周期期間發生的。因此,該第二個處理周期為載入時獲知的目的地完成了所有轉移指令并且為還不具有有效向量的目的地建立了新的處理器。
雖然所述雙處理周期轉換能夠處理許多轉移指令,但是在載入時并不是所有的轉移目的地都得以獲知。某些轉移指令依賴于運行時計算出來的目的地地址。在這些情況下,這些轉移指令從向量空間中獲取它們的本機指令處理程序地址并跳轉到這些位置。如果沒有針對該目的地的有效向量,則動態地產生一個本機指令處理程序并且將其地址加入到所述向量空間中。這一過程是借助動態嘗試來完成的,所述動態嘗試從轉移目的地地址開始并連續進行遺留代碼的運行同步轉換,直到找到一個遺留流程控制指令。該動態嘗試對象建立一個新的LegacyProcedure對象并將用于遺留指令的LegacyInstruction對象裝入其中,直到下一個流程控制指令。然后它請求遺留指令的轉換并將所得到的本機指令提交給存儲器。這個系統能夠處理所有的轉移指令,但是由于進行轉移目的地的預計算能夠實現更好的性能,所以該系統只是用作最后使用的手段。
操作系統調用如上面所提到的,我們知道應用程序是通過系統程序庫函數直接地或間接地進行操作系統調用的。例如,Alpha 21264微處理器體系結構將系統調用定義為一種特定指令。該指令在執行的時候引發一個操作系統中斷。在系統調用指令之前,編譯器和/或編程器必須將系統調用號插入到一個已知的寄存器中,在Alpha 21264微處理器的情況中是$v0。系統調用號從$v0中提取出來并且其它的參數可以從按照系統的函數調用慣用手段定義的其它寄存器中提取出來。對于二進制代碼轉換器而言,系統調用僅僅是另一個指令而已。不過操作系統之間的系統調用號可以是也確實是不同的。舉例來說,OpenVMS操作系統與Tru64 Unix就使用了不同的系統調用號。用于Alpha的Windows NT操作系統也不同于OpenVMS和Tru64。因此,所述二進制代碼轉換器系統調用對遺留操作系統來說必須是特定的。
直接匹配系統調用所述二進制代碼轉換器能夠將每個系統調用映射為接近匹配的主處理器系統調用或者在或不在本機操作系統的幫助下對遺留系統調用的行為進行仿真的代碼。例如,針對Intel IA-64微處理器體系結構編寫的,用于將移除磁盤路徑(rmdir)Alpha Tru64 Unix系統調用轉換為等效的Intel IA-64 Linux系統調用的示范性匯編語言程序在下面示出<pre listing-type="program-listing"><![CDATA[/* *SYS_rmdir *Alpha 137<--->IA-64 l056 * *Inputsr32=char *pathname *Outputsint status */.proc xport_SYS_rmdirxport_SYS_rmdir MapPreamble r86,rTemp1,bSave1 // setup,save return address MakeIA64Addr param0,a0// setup first input mov r15=1056 // setup the syscall number break0x100000 // do syscall AdjustResults // fixup errno/indicator Return bSave1// done,return.endp]]></pre>這一承接程序的地址保存在一個表中,并且當執行Alpha 21264系統調用指令時,處于Alpha寄存器$v0中的系統調用號用作進入該表的索引。在該表位置處的所述地址用于轉移到這承接程序。這一承接程序僅將所需的參數(指向含有目錄名的字符串的指針)移送到Intel型IA-64處理器上的校正寄存器中,并將IA-64系統調用號(1056,而不是Alpha微處理器中的137)放到Intel IA-64微處理器中的寄存器15中。該系統調用返回一個指示值,代表成功的0或代表失敗的-1,該值被置于Alpha微處理器中的校正寄存器中。另一個值,“errno”(錯誤號error number)表示失敗的原因。這個值在Alpha/Tru64系統和IA-64/Linux系統之間是互不相同的,因此必須要對這個值進行轉換。“AdjustResult”宏指令借助另一個數據表來完成這一任務。一旦完成了轉換,errno值就被置于校正Alpha寄存器,并且承接程序準備返回到常規的代碼執行。IA-64中斷指令使用參數0x100000引發這一系統調用。
非直接匹配系統調用前面所述的例子說明了一種對現有的主處理器系統調用存在嚴格匹配的情況。不過,并不總是這樣的。例如,Alpha/Tru64 Unix“uname”系統調用是以多個文本流的形式返回關于機器的信息的。下面的例子就是這種系統調用的匯編語言承接程序的一個例子。
<pre listing-type="program-listing"><![CDATA[/* *SYS_uname *Alpha 207<--->IA-64 1130 * *Inputsr32=struct utsname *buf *Outputsint status */.proc xport_SYS_unamexport_SYS_uname MapPreamble r86,rTemp1,bSave1 // setup,save return address MakeIA64Addr param0,a0 // setup first input(sysname) br.call.sptk.few b0=callsysUname// do as a C function cmp·eq pTemp1,pTemp2=0,IA64Ret //was return value good?(pTemp1)mov v0=0//yes,fix up errno(pTemp1)mov a3=0// and error indicator(pTemp2)mov v0=14 //no,set errno to EFAULT(pTemp2)mov a3=-1 // and error indicator to -1 ReturnbSave1 //done,return.endp]]></pre>對這一系統調用直接進行映射的問題是,遺留程序不是在處理器上運行的,因為最初就是這樣設計的。因此,這一承接程序調用一個C函數而不是直接使用Intel IA-64 Linux“uname”系統調用并對所得到的字符串進行調整。
下面的例子表示用于對Linux“uname”系統調用的行為進行重定義的C函數。注意這一函數是由上面的承接程序中的br.call.sptk.few指令調用的。
<pre listing-type="program-listing"><![CDATA[/* *This is a stub for the uname system call.Additional work must be *done for two reasons1)the size of the strings in the utsname *struct is different between IA-64/Linux and Alpha/OSF,and 2)we *really don’t want an Alpha/OSF program thinking it’s running on *IA-64/Linux. */INT64 callsysUname(char *uts_alpha){ struct utsname uts; //do the syscall,see if it works if(uname(&uts)<0) return-1; //this doesn’t work directly because the IA-64 utsname struct allows //for each string to be 64 bytes but the Alpha only allows for 32 //ALSO--FAKE IT OUT TO LOOK LIKE THE ALPHA! strcpy(&uts_alpha
,“OSF1”); strcpy(&uts_alpha[32],uts.nodename); strcpy(&uts_alpha[64],“VS.1”); strcpy(&uts_alpha[96],“732”); strcpy(&uts_alpha[128],“alpha”); return 0;}]]></pre>需要注意的是雖然使用了Linux“uname”系統調用,但是只有‘nodename,項傳送給了本機結果。虛擬了所有其它的信息組以使得該程序相信它自己是在Tru64 Unix操作系統上運行,例如,版本5.1,build 732。
通過象這樣的技術,能夠重新生成遺留操作系統的整個系統調用組。這一任務的復雜程度取決于遺留和本機操作系統之間的差異。對于Tru64操作系統上運行的Alpha微處理器與Linux操作系統上運行的Intel IA-64微處理器之間進行轉換的情況,它們之間存在著許多的相似之處。
系統程序庫的替換如上面所討論的,可以將系統調用映射到主操作系統中。如上面所提到的,遺留應用程序還與系統程序庫進行聯系。取決于遺留應用程序,使用本機處理器的系統程序庫而不是遺留程序庫是有可能的。這種方法的優點在于本機程序庫有望更好地適于在本機系統上執行。如果不能使用本機程序庫,那么就必須以一種或另一種形式使用遺留程序庫。
靜態與動態鏈接使用系統程序庫的軟件應用程序可以是靜態鏈接的,也可以是動態鏈接的。對于靜態鏈接來說,從程序庫中得到的應用程序所需要的代碼都送入到最終得到的應用程序二進制代碼載入模塊中。這生成了一個很好的但是比動態鏈接要大的載入模塊,動態鏈接是根據需要載入程序庫代碼的。對于動態鏈接的應用程序,在程序運行的時候,必須要用到一個共享程序庫。
靜態鏈接應用程序如果遺留應用程序是靜態鏈接的,那么將有可能無法簡單地用本機程序庫代碼替換靜態鏈接的遺留程序庫代碼。因此,可以利用遺留應用程序的間歇期對遺留程序庫代碼進行轉換。按照本發明的二進制代碼轉換器將不會知道遺留程序庫代碼的存在。不需要額外的遺留組件來產生完全轉換的本機二進制代碼。
動態鏈接應用程序對于使用動態程序庫鏈接的應用程序來說,載入模塊必須含有關于需要哪個程序庫的信息。而且還將給出有關哪些函數是未加解決的函數的信息。就這點來說,通常能夠使用本機程序庫替代遺留程序庫。這種替代是否能夠實現取決于在本機系統上是否存在相同的功能性。如果這樣做了,就需要使用一個簡單的轉換承接程序來將參數轉移到校正寄存器中,這是由于遺留處理器和主處理器之間的函數調用協定很可能互不相同。下面的代碼實例表示一個Intel IA-64匯編語言承接程序的例子,該程序允許使用本機‘atan’(arctangent反正切函數)庫函數代替遺留庫函數。
<pre listing-type="program-listing"><![CDATA[//double atan(double x);.proc atanXportatanXport MapPreamblera,rTemp1,bSave1 // Save IA64 return addr in bSavel movfout0=fa0 // Move arg0 br.call.sptk.many b0=atan // Call ia64 routine movLegacyFpRet=IA64FpRet // Move IA64 return value to legacy Return bSave1 // Return.endp]]></pre>
如上所示,僅需要非常少的代碼就能夠將Intel IA-64‘atan’庫函數映射為Alpha版本,同時所得到的性能較之使用數量相對較大的代碼而言得到了提高。不過,這種方法要求能夠對遺留庫函數進行識別并且要知道它需要那些參數。因此,它僅適用于常用庫函數,而不能用于未知的遺留程序庫。
將遺留函數映射為本機函數的另一種方案是簡單地對遺留程序庫進行代碼轉換。這顯然要求遺留程序庫可用于代碼轉換。這種處理方法得到與靜態鏈接應用相同的結果,只是比使用本機程序庫要復雜一些,這是因為任何可用到的遺留程序庫都將要被使用,不管其所含有的函數是否已知。
存儲器配置附圖6是按照本發明的二進制代碼轉換器中所使用的存儲區域的圖解表示。用附圖標記54和56標示的最前面的兩個存儲區域是第一個處理周期和第二個處理周期微碼區域,如上面所討論的。這些存儲區域含有經轉換的本機指令,這些指令組成了經轉換的遺留應用程序。由附圖標記58標示的下一個區域是含有每個遺留指令處理器的微碼地址的向量空間。如上面所預先指明的,并不是該向量空間中的所有位置都含有有效的條目。該向量空間58所含有的條目的數量與遺留代碼指令的數量相同。最后那個區域是數據空間60。這些是所述遺留應用程序載入模塊中所定義的數據部分。該數據空間60僅僅用于靜態數據或在載入模塊中進行了明確定義的數據。遺留程序可以根據需要從堆陣中或自由存儲空間中指派存儲器。
根據需要,其它的存儲區域也可以提供給經轉換的遺留應用程序。這些存儲區域包括堆棧,該堆棧是從本機處理器存儲器組合中劃撥出來的并且從主處理器堆陣或自由存儲空間中動態地請求存儲空間。
另一個可能存在的區域,它可以或不可以物理地位于所述主處理器存儲器中,是遺留代碼。除了上面所討論的動態嘗試操作以外,一旦完成了代碼轉換,就不再需要這一信息。在這些情況下,可以從一個磁盤文件中將這一信息讀入到保存存儲器中。
寄存器配置按照本發明的二進制代碼轉換器在性能方面一個主要的因素是其使用本機處理器寄存器的方法。下面將給出關于按照本發明的二進制代碼轉換器如何使用本機處理器的寄存器進行其遺留二進制代碼的執行的信息。對于不同的本機處理器來說這一信息可以是不同的。下面的信息是與Intel IA-64本機處理器和Alpha 21264遺留處理器相關的信息。
為了性能的緣故,將遺留處理器寄存器映射到本機處理器寄存器。許多現代微處理器體系結構專門在寄存器中執行幾乎所有的操作并且被迫從存儲器中載入值然后再沒必要地將結果保存回去,導致了相當嚴重的性能惡化。
Alpha 21264處理器具有32個64位通用寄存器和32個64位浮點寄存器。Intel IA-64處理器具有128個64位通用寄存器和128個80位浮點寄存器。下面將給出Alpha/Tru64遺留系統和IA-64本機系統的寄存器配置。
將通用寄存器0-30中的值存儲在IA-64通用寄存器32-62中。
Alpha通用寄存器31總是讀為零并且能夠對其寫入,但是其值總是讀出零。IA-64通用寄存器0具有幾乎相同的特性,因此將Alpha寄存器31映射為Intel IA-64通用寄存器零。
將浮點寄存器0-30中的值存儲在IA-64浮點寄存器32-62中。
Alpha浮點寄存器31總是讀為零并且能夠對其寫入,但是其值將總是讀出零。IA-64浮點寄存器0具有幾乎相同的特性,因此將Alpha浮點寄存器31映射為Intel IA-64浮點寄存器0。
將16個IA-64通用寄存器指定為便箋式或臨時寄存器r63-r78。
將16個IA-64浮點寄存器指定為便箋式或臨時寄存器f63-f78。
將16個IA-64判定寄存器指定為便箋式或臨時寄存器p1-p16。判定寄存器用于存儲比較操作所得到的單位true/false結果。這些寄存器可以與幾乎所有的IA-64指令的執行相對照著使用,以根據條件允許這些IA-64指令的執行。Alpha 21264沒有等效寄存器。
將兩個IA-64轉移寄存器指定為便箋式或臨時寄存器b4-b5。轉移寄存器用于保存轉移指令的目的地地址。Alpha 21264使用通用寄存器來實現這一功能。
二進制代碼轉換器系統的類圖附圖7和8表示二進制代碼轉換器的UML類圖。其中包括了主要的功能組件,這些功能部件還帶有簡要說明。附圖7是按照二進制代碼轉換器的功能單元的順序組織起來的并且重點強調了主系統。這里并沒有表示出所有的類。雖然并不能從這個圖表中明顯地看出,但是一組C++基本類組成了本二進制代碼轉換器的基礎。該組類并不專門適合于任何具體的遺留處理器或主處理器。其中的另一層用于整合本機處理器的專有信息和遺留處理器的專有信息。
附圖8是以等級體系的方式組織的并且表示出了所有類自頂向下的體系結構。其中并沒有示出本二進制代碼轉換器的所有類。
代碼轉換過程示意圖附圖9表示代碼轉換過程示意圖。二進制代碼轉換器會話管理程序對象62位于代碼轉換過程的頂級。它依次對遺留處理程序子系統36和本機處理程序子系統40進行調用。該圖中示出了六個總體步驟1.載入程序子系統34用于載入遺留程序。將遺留數據段無修改地提交給存儲器。遺留指令傳給該系統的用于代碼轉換的其余部分。
2.然后確定遺留指令的類型并且將這些遺留指令組合為以流程控制指令結束的遺留指令組。本步驟的輸出是一系列的LegacyProcedure對象,它們的每一個都含有LegacyInstruction對象的總量。這些對象的集合是遺留程序的指令部分。
3.如果存在轉換前優化模塊64并且該模塊是有效的,則對其進行調用。這些模塊對步驟2中生成的LegacyProcedure和LegacyInstruction對象進行操作。
4.將LegacyInstruction轉換為本機處理器指令。本步驟的輸出是NativeInstruction對象,將這些對象添加到各個LegacyProcedure對象中。所有本機指令對象的集合是經轉換程序的指令部分。
5.如果存在轉換后優化模塊66并且該模塊是有效的,則對其進行調用。這些模塊可能會利用LegacyProcedure和/或LegacyInstruction對象對步驟4中生成的NativeInstruction對象進行操作。
6.最后一個步驟是將經轉換的程序提交給本機處理器存儲器以準備執行或交付給一個由標有“輸出程序”的塊68表示的磁盤文件以便今后使用。
指令轉換實例下面將給出用于將幾個具有代表性的Alpha 21264指令轉換為IA-64指令的代碼的實例。Alpha標準型使用這樣一種指令轉換結構方式,該結構方式為每個遺留Alpha指令提供一個稱為遺留指令轉換器的C函數并且為每個IA-64指令提供一個稱為本機指令發生器的C函數。之所以使用C函數是因為它們的地址能夠保存在一個表中以便有效訪問。所述指令轉換器對遺留指令進行檢查、提取操作代碼并彈出用于該條Alpha指令的遺留指令轉換器函數的地址。該遺留指令轉換器函數根據需要反過來使用本機指令發生器來產生IA-64指令。下面將對兩個Alpha指令的例子進行探討。
ALPHA S4ADDQ,文字形式這條指令是一條用于將一個文字值加到一個已經存在于寄存器中的值上的整型加法指令。下面給出的第一個例子表示用于這條Alpha指令的遺留指令轉換器。該函數調用兩個不同的IA-64指令發生器函數shladd和add_i14。這些C函數產生復制Alpha S4ADDQ指令的行為所需的IA-64二進制指令。在調用了每個IA-64指令發生器函數之后,這些IA-64指令就被添加到轉換器子系統中以等候將其提交給本機處理器存儲器和/或磁盤文件之前的進一步處理。
遺留指令轉換器函數被Alpha到IA-64轉換器用于將Alpha 21264指令轉換為IA-64等價指令。在這種情況下,需要兩個IA-64指令。對于其它的遺留指令來說,將會需要更多或更少的指令。下面的第二個例子表示產生IA-64‘shladd’指令所需要的IA-64指令發生器函數。
<pre listing-type="program-listing"><![CDATA[/* *This function translates the Alpha instruction Scaled Add Quadword by 4. *S4ADDQ multiplies Ra by 4 and adds it to lit.The 64-bit sum is stored in Rc */INT64 S4ADDQ_LIT(Translator *translator,UINT64 Ra,UINT64 1it,UINT64 Rc){ NativeInstruction instr; //Get the necessary temp registers UINT64 rTemp1=translator->regMaps->getGPTempReg (); //Get the mapped IA64 registers for the input Alpha registers Ra=translator->regMaps->getMappedIA64GenReg (Ra); Rc=translator->regMaps->getMappedIA64GenReg (Rc); //Writes to the zero reg produce faults in IA64 but not in Alpha if(Rc!=GPRegZero) { //rTemp1=Ra * 4 shladd(translator,&instr,PredRegZero,rTemp1,Ra,2,GPRegZero); translator->addNativeInstruction(&instr); //Rc=rTemp1+1it adds_i14(translator,&instr,PredRegZero,Rc,1it,rTemp1); translator->addNativeInstruction(&instr); } return 0 ;}]]></pre>Alpha S4ADDQ文字形式指令轉換器函數<pre listing-type="program-listing"><![CDATA[//******************************************************************************//******************************************************************************// This function generates type A2 instructions.void genA2(Translator *translator,NativeInstruction *inst,UINT64 x4,UINT64 qp, UINT64 r1,UINT64 r2,UINT64 ct2,UINT64 r3){ inst->instr =(8UL<<37)|(x4<<29)|(ct2<<27)|qp|(r1<<6)| (r2<<13)|(r3<<20); inst->type=ALU; translator->regMaps->getGenRegMask(inst->srcRegsUsed,r2,r3); inst->srcRegType =General; translator->regMaps->getGenRegMask(inst->destRegUsed,r1); inst->destRegType =General; inst->predReg =translator->regMaps->getPredRegMask(qp);}void shladd(Translator *translator,NativeInstruction *inst,UINT64 qp,UINT64 r1, UINT64 r2,UINT64 count,UINT64 r3){ //IA64 needs count to be 1 less than actual number of bits to be shifted count--; genA2(translator,inst,4,qp,r1,r2,count,r3);}]]></pre>用于‘shladd’指令的IA-64指令發生器函數還需要注意的是寄存器重映射函數也是由遺留指令轉換器進行處理的。另一個需要重點注意的問題是,在IA-64上執行這個Alpha指令需要一個單臨時寄存器。
ALPHA CMOVEQAlpha CMOVEQ指令根據條件將一個值移送到一個Alpha通用寄存器中。用于這個指令的遺留指令轉換器可以在下面的例子中找到。這個Alpha指令再一次需要兩個IA-64指令,cmp.eq(8位直接形式)和add(寄存器形式)。
<pre listing-type="program-listing"><![CDATA[ /* *This function translates the Alpha instruction Conditional Move if Register *Equal to Zero,If register Ra is equal to 0,Rb is written to Rc. */INT64 CMOVEQ(Translator *translator,UINT64 Ra,UINT64 Rb,UINT64 Rc){ NativeInstruction instr; //Get the necessary temp registers UINT64 pTemp1=translator->regMaps->getPredTempReg (); UINT64 pTemp2=translator->regMaps->getPredTempReg (); //Get the mapped IA64 registers for the input Alpha registers Ra=translator->regMaps->getMappedIA64GenReg (Ra); Rb=translator->regMaps->getMappedIA64GenReg (Rb); Rc=translator->regMaps->getMappedIA64GenReg (Rc); //Writes to the zero reg produce faults in IA64 but not in Alpha if(Rc!=GPRegZero ) ( //Determine if Ra is equal to zero cmp_eq_i8(translator,&instr,PredRegZero,pTemp1,pTemp2,0,Ra); translator->addNativeInstruction(&instr); //conditionally do the move add_r(translator,&instr,pTemp1,Rc,GPRegZero,Rb); translator->addNativeInstruction(&instr); } return 0;}]]></pre>Alpha CMOVEQ遺留指令轉換器函數優化程序實例-IA-64代碼調度程序優化程序下面的優化程序實例通過嘗試對經轉換的指令進行最佳調度利用IA-64 EPIC體系結構來實現指令并行度的最大化。Itanium 2處理器每時鐘周期能夠執行多達6條指令。必須將這些指令組成為具有3個41位指令以及一個5位template域的指令束,其中所述5位template域代表執行這些指令需要那些處理器資源。該優化程序對本機指令進行分析,以根據數據相關性判定哪些指令可以安全地并行執行,然后選擇指令束來匹配那些指令組。在附圖10中示出了這一總體過程。按照本發明的二進制代碼轉換器將遺留程序分解為多個遺留指令組70。IA-64調度優化程序然后將經轉換的本機等價指令分解為IA-64指令組72、74、76。一個IA-64指令組中的所有指令能夠同時得以執行,因此,在它們彼此之間不包含數據相關性。該優化程序然后將IA-64指令組72、74、76分解為各自具有3條指令的IA-64指令束78、80、82、84、86和88。
這一調度算法僅應用于Itanium 2和較新的IA-64處理器。不過,各種本機處理器都可以合理地受益于適用于它們的體系結構的簡明指令調度算法。
IA-64體系結構限定了有限數量的束類型。在同一個束中并不是所有的IA-64指令的組合都是合法的。例如,一種標識為MMI的常用束類型,這代表在該束中含有兩個存儲器指令和一個整型指令。這些束的類型被編碼在這些束的5位template域中。謹慎選取束類型對避免處理器停頓來說是很重要的。最終,IA-64調度程序優化程序使用一種謹慎設計的算法來為一個指令組中的IA-64指令選擇束類型。附圖11中示出了一種示范性的算法。
轉換過程實例下面的例子是一個針對Alpha遺留處理器和一個IA-64本機處理器的例子。將一組四個遺留Alpha指令轉換為IA-64指令并且為這個本機處理器對這些指令進行適當的組織。
附圖12表示一小塊Alpha指令以及將它們轉換為IA-64指令的過程的圖解說明。這個附圖只表示了代碼轉換步驟,而并沒有優化處理。遺留代碼塊總是以某種類型的流程控制指令結束,通常是跳轉指令或轉移指令,并且將這些遺留代碼塊稱為遺留進程(雖然從初始源代碼的觀點來說它們可能并不真正代表一個完整的遺留進程)。遺留進程中的所有指令是順序地執行的。這個例子假設已將遺留程序分解為各個遺留進程并且單個進程的代碼轉換正在進行。
代碼轉換過程包括獲取單條遺留指令、根據操作碼(opcode)利用一個查找表格對其進行解碼以及調用適當的遺留指令代碼轉換器函數,然后其按照需要構造本機處理器指令。這一過程一般包括下述步驟1.可能需要一個或多個暫時(臨時)寄存器。如果是這種情況,它們是從負責寄存器映射的X-port對象中申請的。對于IA-64本機處理器來說,是將IA-64的128個通用寄存器的一部分貢獻出來用作暫時寄存器的。
2.將遺留指令所使用的所有的遺留寄存器均映射為它們相應的主處理器寄存器。再一次,還是由X-port的寄存器映射組件來進行這一服務。
3.既然已經對寄存器進行了映射并且對暫時寄存器進行了指定,那么如果需要,遺留代碼變換器函數調用本機指令發生器函數來以自然二進制形式產生主處理器指令。就這個例子來說,需要七個不同的IA-64指令(sxt4使用了三次),并且,從而,使用了七個不同的本機指令發生器函數。
這一過程的輸出是一組連續時序本機處理器指令,它們最終執行與遺留指令相同的功能。在附圖12中,對每個所得到的IA-64主處理器指令進行了編號,以供進一步引用。如圖中所看到的,對于所示的哪個Alpha指令,需要九個IA-64指令來進行正確的仿真。這一數量可多可少,這取決于遺留指令的混合程度。
該組指令可就此打成一個程序包并照現在這樣執行,不過這可能會導致IA-64主處理器的較差的性能。下述內容簡要介紹了為了提高性能應當如何對這些指令進行封包處理。雖然這一信息是IS-64專用的,但是其它的主處理器也能夠進行并且需要類似的代碼重組來實現最高性能。
IA-64體系結構需要將這些指令組合為指令束。指令束的編排方式見附圖13。每個束由三個IA-64指令組成,每個指令的長度是41位。每個束還含有一個5位template域,它用于說明這一組三個指令所需要的處理器資源。這些資源是處理器執行單元。
附圖14表示一個Itanium 2處理器中能夠使用的執行單元。這些執行單元包括四個儲存器單元(它們還能夠執行許多簡單的整型和邏輯指令)、兩個整型單元、兩個浮點單元(它們還能夠執行長指令或擴展指令)以及三個轉移單元。該附圖還示出了這些單元是如何由一組兩個指令束使用的。這將在下面做進一步介紹。需要注意的是,如果有足夠的處理器資源可以使用,IA-64處理器每次能夠執行兩個完整的指令束(六條指令)。
束中的template域指明了該束中的指令需要哪些執行單元的組合。例如,template域值16代表代碼MIB,它意謂著需要使用一個存儲器單元、一個整型單元和一個轉移單元。Template域還可以規定一個stop條件,它意謂著所有當前執行的指令都必須在處理器接收到任何新的指令之前完成。Stop用于防止數據相關性的擾亂。Template 17也是一個MIB類型,只是在束的終端規定了一個stop。它由符號MIB表示。
術語IA-64指令組涉及全部都符合并行執行的條件的一組IA-64指令。IA-64指令組最終都要組成為一個或多個末尾處必須含有一個stop的指令束。
使用關于IA-64主體系結構的這一信息,可以對代碼轉換過程的下一步驟進行檢驗。附圖15表示用于IA-64主處理器的下一步驟。
附圖15表示從附圖12得到的彼此之間不含數據相關性的一組指令。這是一個單一的IA-64指令組。
IA-64主處理器具有良好性能的必要條件是,以不允許數據相關性擾亂的順序對指令進行適當的調度以最大化并行度。因此,IA-64的X-port的專用部分進行對附圖12中所發出的指令流的分析,并且判斷哪些指令可以安全地同時執行。在附圖15中,可以看到指令1、2、5、6和8彼此之間不具有寄存器相關性,并因此,它們能夠安全地并行執行。不過,這是五條指令的一個序列。必須對IA-64指令束進行選定以含有這些指令。然后將所得到的指令束提交給存儲器作為可執行IA-64代碼的一部分。需要注意的是,IA-64 movl指令需要兩個束位置。
附圖16表示第二個IA-64指令組,它僅含有三條指令(3、7和9)。這個IA-64指令組適合于一個的MIB型單束。雖然在本例中沒有出現,但是有可能出現沒有將指令束全部填滿的情況。在這些情況中,可以將不操作代碼插入到任意束位置中以使束完整。IA-64指令束的構成代表這一過程的結束。一旦構成了這種形式,IA-64指令就可由主處理器直接執行了。
轉換后優化實例下述內容是一個可以在代碼轉換發生之后進行調用的優化程序的實例。該實例采用了一個Alpha遺留處理器和一個IA-64本機處理器。其目的是使用IA-64主處理器的稱為判斷的功能來消除短正向轉移。判斷允許根據條件指向一條或多條指令。
下面的例子表示一個簡單的C語言if-then結構,用于說明使用IA-64判斷功能的原因。(假設寄存器r5為a,r6為b,而r7為c。)如所看到的,如果a大于b,則變量c將會具有值0。否則,c將等于1。這種語句可以用圖中所示的匯編語言表示。
<pre listing-type="program-listing"><![CDATA[ if (a>b) { c=0; } else { c=1; }//PowerPC implementation--a conditional branch and an unconditional//branch are requiredcmpgtr5,r6 // compare′a′and′b′beq a_gt_b //jump if trueli r7,1 //c=1(false case)bdonea_gt_bli r7,0 //c=0(true case)done //continue executing here//IA-64 implementation--no branches required cmp.gt p1,p2=r5,r6 //compare′a′and′b′(p1) mov r7=o //if a>b,c=o(p2) mov r7=1 //else,c=1]]></pre>用匯編語言的等價語句簡化C語言的if-then語句絕大部分的現代微處理器體系結構需要使用一個或多個轉移指令來根據條件為c賦值。然而IA-64執行時不需要,其原因就是判斷功能。IA-64 cmp.gt指令對r5和r6進行比較并將一個true或false(1或0)值保存到判定寄存器p1和p2中。這兩個寄存器中的結果被用于根據條件執行下兩條指令。第一個mov只有當p1=1時執行。第二個mov只有當p2=1時執行。由于所給出的比較指令的比較的ture或flase結果返回到p1中并且將該結果的求反值返回到p2中,因此只有一條mov指令是有效的。而另一條指令將不會執行。
這一概念可以用于消除短正向條件轉移。附圖17表示一小段含有一個短正向條件轉移指令(BEQ)的Alpha代碼。如果該轉移出現在地址100C,則1010和1014處的指令將不執行。如果轉移條件沒有得到滿足,則該轉移失敗并且前面說的那兩條指令將會執行。
如該圖所顯示的,BEQ指令可以由一個IA-64比較指令代替,該比較指令將其結果保存到IA-64判定寄存器中。然后可以利用這些判定寄存器根據條件執行對應于Alpha ORNOT和ADDQ指令的IA-64等價代碼,從而消除了一個不必要的條件轉移。這是非常有益處的,因為現代微處理器是沿著它們確信正確的指令路徑嘗試預取指令的。如果處理器錯誤地判定了條件轉移發生與否,將會造成性能惡化,這是因為必須對已經存在于處理器的(多個)管道中的誤判指令進行刷新,并且必須沿著備用通路提取指令來執行。出于這些原因,只要有可能,對條件轉移的消除通常是合乎需要的。
這個優化程序實例是一個能夠利用本機處理器中有而遺留處理器中沒有的功能的例子。
該優化模塊對經代碼轉換的遺留代碼(所得到的IA-64代碼)進行搜索來查找短正向條件轉移。當其發現了這些條件轉移時,它就消除這些轉移,產生用于比較的IA-64二進制代碼,并修改將要進行判定的指令。這一過程是在代碼轉換完成之后且在將本機指令提交給存儲器以備執行之前發生的。因此,還是有可能改變它們的行為的。
轉換前優化實例下面是轉換前優化的一個例子。它允許內嵌地執行函數。內嵌是一種編譯器技術,它以“聯機”的方式展開函數的內容,而不是設置為跳轉到函數本身。適于內嵌的函數通常是短小并且不經常調用其它函數的函數。函數內嵌的缺點是無論在哪里調用函數,都要對該函數的代碼進行復制。這增加了程序對存儲器的需求量。不過,現代本機處理器,例如IA-64,可能含有數十億字節的隨機存取存儲器。對于這種處理器來說,根本察覺不到函數內嵌對存儲器造成的影響。
下面的例子表示一個小的C語言代碼實例。這里,funcX調用funcY,funcY執行一個非常簡單的操作。優化編譯器可以根據編程器所選定的最佳條件選擇決定內嵌funcY。
<pre listing-type="program-listing"><![CDATA[ int funcX(int a) {funcY(a);//call funcY } int funcY(int b) { return b+7; } 調用一個小的C函數的C函數]]></pre>另一方面,按照本發明的二進制代碼轉換器能夠在更廣泛范圍內選擇用于為了速度而犧牲存儲器使用率的內嵌的指令。對于每個內嵌的函數來說,可以省略遺留代碼的下述部分1.初始化代碼通常為了執行函數調用需要有一定數量的初始化。
該數量很可能是在多達六條遺留指令的范圍之內,不過在平臺與平臺之間可能是不同的。
2.無條件轉移一種‘跳轉’指令,將代碼執行引導到所正在被調用的函數。
3.函數引導程序通常,函數包含某種類型的引導程序,通常由幾個指令組成。引導程序中所執行的操作包括為數據區建立全局指針。
4.函數調用返回從函數返回通常包括一些清除指令。
5.無條件轉移一種‘返回’指令,將代碼執行引導到進行調用的函數。
在許多情況下,由于能夠消除大量的遺留代碼,內嵌函數能夠實現性能的提高。
這個優化程序是在遺留代碼得以轉換之前但是在已經對遺留代碼進行組合之后對遺留代碼產生作用的。它搜索函數調用,并且當其發現一個合法的內嵌函數時,就為該二進制代碼轉換系統插入提示。
除了具有充足的存儲器使內嵌比起最初的遺留系統來講更加可行之外,這種優化方法并不是專門針對IA-64主處理器的性能而設計的。
顯然,根據上述的教導,本發明的許多修改和改變都是可能實現的。因此,應當明白,在所附的權利要求書的范圍之內,除了上面所具體說明的方式之外,還可以以其它的方式實現本發明。
權利要求
1.一種二進制代碼轉換器,包括一個載入程序子系統,用于讀取遺留二進制指令并將其載入到一個文件當中;和一個代碼轉換器,用于直接將所述遺留二進制指令轉換為本機二進制指令,所述代碼轉換器對于使用不同的遺留處理器和本機處理器的應用來說是可重新配置的。
全文摘要
本發明為一種終極管道和最優重排技術,涉及用于將針對遺留處理器編寫的二進制指令直接轉換為本機處理器可執行的二進制指令的二進制代碼轉換器。按照本發明的一個重要方面,將所述二進制代碼轉換器配置成為一種可重新配置的代碼轉換器,這使得該二進制代碼轉換器能夠用于不同的遺留處理器和/或操作系統和本機處理器。該二進制代碼轉換器還進行優化,以利用更有效的本機處理器指令,并允許禁用部分遺留二進制代碼和/或將新的本機指令加入到應用程序中而無需改變遺留二進制代碼。
文檔編號G06F17/00GK1570870SQ20041000696
公開日2005年1月26日 申請日期2004年3月1日 優先權日2003年3月13日
發明者E·W·茲沃納, G·P·克勞克, J·C·肯耐爾, T·R·郝瑞格, W·J·坎農 申請人:諾斯羅普-格魯曼公司