| PowerPC體系結構初探 從超級計算機到游戲控制臺,從服務(wù)器到手機,隨處可見(jiàn) PowerPC 處理器的身影 -- 它們的體系結構全都相同。本篇對 PowerPC 應用級編程模型的介紹概述了指令集、重要的寄存器以及其他細節,這些細節對于開(kāi)發(fā)可靠的、高性能的 PowerPC 應用程序和保持代碼在不同處理器的兼容性來(lái)說(shuō)是必須要了解的。 對 PowerPC 體系結構家族樹(shù)的所有分支來(lái)說(shuō),PowerPC 體系結構和應用級編程模型是通用的。要獲得詳細的資料,請參閱 IBM® PowerPC Web 站點(diǎn)技術(shù)庫中的產(chǎn)品用戶(hù)手冊(參閱 參考資料以獲取鏈接)。 PowerPC 體系結構是一種精減指令集計算機(Reduced Instruction Set Computer,RISC)體系結構,定義了 200 多條指令。PowerPC 之所以是 RISC,原因在于大部分指令在一個(gè)單一的周期內執行,而且通常只執行一個(gè)單一的操作(比如將內存加載到寄存器,或者將寄存器數據存儲到內存)。 PowerPC 體系結構分為三個(gè)級別(或者說(shuō)是“book”)。通過(guò)對體系結構以這種方式進(jìn)行劃分,為實(shí)現可以選擇價(jià)格/性能比平衡的復雜性級別留出了空間,同時(shí)還保持了實(shí)現間的代碼兼容性。 Book I. 用戶(hù)指令集體系結構 定義了通用于所有 PowerPC 實(shí)現的用戶(hù)指令和寄存器的基本集合。這些是非特權指令,為大多數程序所用。 Book II. 虛擬環(huán)境體系結構 定義了常規應用軟件要求之外的附加的用戶(hù)級功能,比如高速緩存管理、原子操作和用戶(hù)級計時(shí)器支持。雖然這些操作也是非特權的,但是程序通常還是通過(guò)操作系統調用來(lái)訪(fǎng)問(wèn)這些函數。 Book III. 操作環(huán)境體系結構 定義了操作系統級需要和使用的操作。其中包括用于內存管理、異常向量處理、特權寄存器訪(fǎng)問(wèn)、特權計時(shí)器訪(fǎng)問(wèn)的函數。Book III 中詳細說(shuō)明了對各種系統服務(wù)和功能的直接硬件支持。 從最初的 PowerPC 體系結構的開(kāi)發(fā)開(kāi)始,就根據特定的市場(chǎng)需求而發(fā)生分支。當前,PowerPC 體系結構家族樹(shù)有兩個(gè)活躍的分支,分別是 PowerPC AS體系結構和 PowerPC Book E體系結構。PowerPC AS 體系結構是 IBM 為了滿(mǎn)足它的 eServer pSeries UNIX 和 Linux 服務(wù)器產(chǎn)品家族及它的 eServer iSeries 企業(yè)服務(wù)器產(chǎn)品家族的具體需要而定義的(參閱 參考資料中的鏈接以獲得更多資料)。PowerPC Book E 體系結構,也被稱(chēng)為 Book E,是 IBM 和 Motorola 為滿(mǎn)足嵌入式市場(chǎng)的特定需求而合作推出的。PowerPC AS 所采用的原始 PowerPC 體系結構與 Book E 所采用的擴展之間的主要區別大部分集中于 Book III 區域中。 在這些衍生的體系結構中還有一些適當的應用級擴展,這些擴展大部分與具體應用的場(chǎng)合相關(guān),但是 PowerPC AS 和 PowerPC Book E 共享在 PowerPC 體系結構的 Book I 中定義的基本指令集。雖然三種體系結構主要在操作系統級別上表現出不同,但它們在很大程度上具備應用級的兼容性。 PowerPC 最初定義了同時(shí)對 32 位和 64 位實(shí)現的支持,可以讓 32 位的應用程序運行于 64 位系統之上。在 IBM pSeries 和 iSeries 服務(wù)器上使用的 PowerPC AS 系統現在只提供體系結構的 64 位實(shí)現,新的 64 位應用程序和遺留的 32 位的應用程序可以運行于同一個(gè)系統之上。PowerPC Book E 體系結構同時(shí)有 32 位實(shí)現和 64 位實(shí)現,64 位實(shí)現也完全兼容 32 位 PowerPC 應用程序。這兩種體系結構都具備與 PowerPC Book I 指令和寄存器的完全兼容性,同時(shí)提供了對內存管理、異常和中斷、計時(shí)器支持和調試支持等各方面的系統級擴展。 最初的 PowerPC 體系結構仍是 PowerPC AS 和 PowerPC Book E 的主要組成部分,并仍保持了其完整性,表現出了令人信服的應用級兼容性。 PowerPC 應用程序編程模型 當用到不只一種類(lèi)型的 PowerPC 處理器時(shí),開(kāi)發(fā)人員應時(shí)刻謹記處理器處理內存的方式存在一些差異。 PowerPC 存儲模型 PowerPC 體系結構本身支持字節(8 位)、半字(16 位)、字(32 位) 和雙字(64 位) 數據類(lèi)型。PowerPC 實(shí)現還可以處理最長(cháng) 128 字節的多字節字符串操作。32 位 PowerPC 實(shí)現支持 4-gigabyte 的有效地址空間,而 64 位 PowerPC 實(shí)現支持 16-exabyte 的有效地址空間。所有存儲都可以字節尋址。 對于錯位數據訪(fǎng)問(wèn)來(lái)說(shuō),不同的產(chǎn)品家族提供了不同的校準支持,有一些是以處理異常的方式,其他的是通過(guò)硬件中的一步或者多步操作來(lái)處理訪(fǎng)問(wèn)。 最高位字節在最前(Big-endian)還是最低位字節在最前(little-endian)? PowerPC、PowerPC AS 以及早期的 IBM PowerPC 4xx 家族大部分是字節排列順序最高位在最前的機器,這就意味著(zhù)對半字、字以及雙字訪(fǎng)問(wèn)來(lái)說(shuō),最重要的字節(most-significant byte,MSB)位于最低的地址。各實(shí)現對最低位在最前的字節排列順序方式的支持不同。PowerPC 和 PowerPC AS 提供了最小限度的支持,而 4xx 家族為最低位字節在最前的存儲提供了更為健壯的支持。Book E 是字節排列順序無(wú)關(guān)的,因為 Book E 體系結構完全支持這兩種訪(fǎng)問(wèn)方法。 回頁(yè)首 PowerPC 應用級寄存器 PowerPC 的應用級寄存器分為三類(lèi):通用寄存器(general-purpose register,GPR)、浮點(diǎn)寄存器(floating-point register [FPR] 和浮點(diǎn)狀態(tài)和控制寄存器 [Floating-Point Status and Control Register,FPSCR])和專(zhuān)用寄存器(special-purpose register,SPR)。讓我們來(lái)分別看一下這三類(lèi)寄存器。 通用寄存器(GPR) 用戶(hù)指令集體系結構(Book I)規定,所有實(shí)現都有 32 個(gè) GPR(從GPR0 到 GPR31)。GPR 是所有整數操作的源和目的,也是所有加載/存儲操作的地址操作數的源。GPR 還提供對 SPR 的訪(fǎng)問(wèn)。所有 GRP 都是可用的,只有一種情況例外:在某些指令中,GPR0 只是代表數值 0,而不會(huì )去查找 GPR0 的內容。 浮點(diǎn)寄存器(FPR) Book I 規定,所有實(shí)現都有 32 個(gè) FPR(從 FPR0 到 FPR31)。FPR 是所有浮點(diǎn)操作的源和目的操作數,可以存放 32 位和 64 位的有符號和無(wú)符號整數,以及單精度和雙精度浮點(diǎn)數。FPR 還提供對 FPSCR 的訪(fǎng)問(wèn)。 注意,嵌入式微處理器實(shí)現時(shí)經(jīng)常不提供對浮點(diǎn)指令集的直接硬件支持,或者只是提供一個(gè)附加浮點(diǎn)硬件的接口。很多嵌入式應用程序很少或者根本不需要浮點(diǎn)算法,而當需要的時(shí)候,對 PowerPC 浮點(diǎn)指令執行進(jìn)行軟件仿真就足夠了。在嵌入式微處理器中,硬件中省去浮點(diǎn)(支持)而為實(shí)現帶來(lái)的芯片面積和功率的減少是至關(guān)重要的。 浮點(diǎn)狀態(tài)和控制寄存器(FPSCR)捕獲浮點(diǎn)操作的狀態(tài)和異常結果,FPSCR 還具有控制位,以支持特定的異常類(lèi)型和對四種舍入模式之一的選擇。對 FPSCR 的訪(fǎng)問(wèn)要通過(guò) FPR。 專(zhuān)用寄存器(SPR) SPR 給出處理器核心內部資源的狀態(tài)并對其進(jìn)行控制。不需要系統服務(wù)的支持就可以由應用程序讀寫(xiě)的 SPR 包括計數寄存器(Count Register)、鏈接寄存器(Link Register)和整型異常寄存器(Integer Exception Register)。需要系統服務(wù)的支持才可以由應用程序讀寫(xiě)的 SPR 包括時(shí)基(Time Base)和其他各種可能支持的計時(shí)器。 * 指令地址寄存器(Instruction Address Register,IAR) 這個(gè)寄存器就是程序員們所熟知的 程序計數器或者 指令指針。它是當前指令的地址。這實(shí)際上是一個(gè)偽寄存器,用戶(hù)只能通過(guò)“branch and link”指令才能直接使用這個(gè)寄存器。IAR 主要是由調試器使用,顯示將要被執行的下一條指令。 * 鏈接寄存器(Link Register,LR) 這個(gè)寄存器存放的是函數調用結束處的返回地址。某些轉移指令可以自動(dòng)加載 LR 到轉移之后的指令。每個(gè)轉移指令編碼中都有一個(gè) LK 位。如果 LK 為 1,轉移指令就會(huì )將程序計數器移為 LR 中的地址。而且,條件轉移指令 bclr 轉移到 LR 中的值。 * 定點(diǎn)異常寄存器(Fixed-Point Exception Register,XER) 這個(gè)寄存器存放整數運算操作的進(jìn)位以及溢出信息。它還存放某些整數運算操作的進(jìn)位輸入以及加載和存儲指令( lswx 和 stswx )中傳輸的字節數。 * 計數寄存器(Count Register,CTR) 這個(gè)寄存器中存放了一個(gè)循環(huán)計數器,會(huì )隨特定轉移操作而遞減。條件轉移指令 bcctr 轉移到 CTR 中的值。 * 條件寄存器(Condition Register,CR) 這個(gè)寄存器分為八個(gè)字段,每個(gè)字段 4 位。很多 PowerPC 指令將指令的第 31 位編碼為 Rc 位,有一些指令要求 Rc 值等于 1。當 Rc 等于 1 且進(jìn)行整數操作時(shí),CR 字段 0 被設置來(lái)表示指令操作的結果:相等(Equal, EQ),大于(Greater Than, GT),小于(Less Than, LT),以及和溢出(Summary Overflow, SO)。當 Rc 等于 1 且進(jìn)行浮點(diǎn)操作時(shí),CR 字段 1 被設置用來(lái)表示 FPSCR 中異常狀態(tài)位的狀態(tài):FX、FEX、VX 和 OX。任何一個(gè) CR 字段都可以是整數或者浮點(diǎn)比較指令的目標。CR 字段 0 還被設置用來(lái)表示條件存儲指令( stwcx 或者 stdcx ) 的結果。還有一組指令可以操縱特定的 CR 位、特定的 CR 字段或者整個(gè) CR,通常為了測試而將幾個(gè)條件組合到同一個(gè)位中。 * 處理器版本寄存器(Processor Version Register,PVR) PVR 是一個(gè) 32 位只讀寄存器,標識處理器的版本和修訂級別。處理器版本由 PowerPC 體系結構過(guò)程分配。修訂級別由實(shí)現定義。需要有特權才能訪(fǎng)問(wèn) PVR,所以應用程序只能在操作系統函數的幫助下才可以確定處理器版本。 回頁(yè)首 PowerPC 應用級指令集 表 1 列出了不同的指令類(lèi)別以及每類(lèi)的指令類(lèi)型。 表 1. 指令類(lèi)別 指令類(lèi)別 基本指令 Branch branch, branch conditional, branch to LR, branch to CTR Condition register crand, crnor, creqv, crxor, crandc, crorc, crnand, cror, CR move Storage access load GPR/FPR, store GPR/FPR Integer arithmetic add, subtract, negate, multiply, divide Integer comparison compare algebraic, compare algebraic immediate, compare logical,compare logical immediate Integer logical and, andc, nand, or, orc, nor, xor, eqv, sign extension, countleading zeros Integer rotate/shift rotate, rotate and mask, shift left, shift right Floating-point arithmetic add, subtract, negate, multiply, divide, square root, multiply-add,multiply-subtract, negative multiply-add, negative multiply-subtract Floating-point comparison compare ordered, compare unordered Floating-point conversion round to single, convert from/to integer word/doubleword FPSCR management move to/from FPSCR, set/clear FPSCR bit, copy FPSCR field to CR Cache control touch, zero, flush, store Processor management system call, move to/from special purpose registers, mtcrf, mfcr 指令解析 所有指令的編碼長(cháng)度都是 32 位。PowerPC 的位編號方式與大部分其他定義相反:第 0 位是最重要的位,第 31 位是最不重要的位。指令首先由一個(gè)字段中較高的 6 位進(jìn)行解碼,這 6 位稱(chēng)為 主要操作碼(primary opcode)。其余 26 位包含的字段分別是操作數說(shuō)明、立即(immediate)操作數以及擴展的操作碼(opcode),而且這些還可能是保留的位或字段。表 2 列出了 PowerPC 定義的基本指令格式。 表 2. PowerPC 指令格式 格式 0 6 11 16 21 26 30 31 D-form opcd tgt/src src/tgt immediate X-form opcd tgt/src src/tgt src extended opcd A-form opcd tgt/src src/tgt src src extended opcd Rc BD-form opcd BO BI BD AA LK I-form opcd LI AA LK * D-form 這一指令格式提供至多兩個(gè)寄存器作為源操作數,一個(gè)立即源,至多兩個(gè)寄存器作為目的操作數。這一指令格式的一些變種使用部分目的和源寄存器操作數說(shuō)明符作為立即字段或作為擴展的操作碼。 * X-form 這一指令格式提供至多兩個(gè)寄存器作為源操作數,至多兩個(gè)目的操作數。這一指令格式的一些變種使用部分目的和源寄存器操作數說(shuō)明符作為立即字段或作為擴展的操作碼。 * A-form 這一指令格式提供至多三個(gè)寄存器作為源操作數,以及一個(gè)目的操作數。這一指令格式的一些變種使用部分目的和源寄存器操作數說(shuō)明符作為立即字段或作為擴展的操作碼。 * BD-form 條件轉移指令使用的是這一指令格式。BO 指令字段指定了條件的類(lèi)型;BI 指令字段指定了以哪個(gè) CR 位作為條件;BD 字段用作轉移位置。AA 位指定了轉移是絕對轉移還是相對轉移。換名話(huà)說(shuō),轉移目標地址是立即字段的值,還是立即字段的值與轉移地址的和。LK 位指定了下一個(gè)順序指令的地址是否作為子例程調用的返回地址保存在鏈接寄存器中。 * I-form 無(wú)條件轉移指令使用這一指令格式。由于是無(wú)條件的,BD 格式中的 BO 和 BI 字段改變?yōu)榱硗獾霓D移位置,以構成 LI 指令字段。同 BD 格式一樣,這一指令格式也支持 AA 和 LK 位。 如前所述,這些指令格式各有其變種。不過(guò),這些格式是對大部分 PowerPC 指令集編碼結構的最好描述。 轉移指令 PowerPC 為控制流程提供了一組指令,包括: * 條件和無(wú)條件轉移指令。 * “遞減計數和如果是零或者非零時(shí)轉移”的能力。 * 絕對轉移和相對轉移。 * 使用鏈接寄存器或計數寄存器來(lái)指定轉移目標地址的轉移指令。 所有的轉移指令都具備保存后繼順序指令地址的能力,包括到鏈接寄存器的轉移。條件寄存器 32 位中的任意一位都可以指定為條件轉移的條件,并可以指定 CR 位是否必須為 0 或 1 時(shí)轉移條件才成立。 條件寄存器指令 PowerPC 提供了一組用于對 CR 的特定位執行布爾操作和對 CR 字段進(jìn)行拷貝的指令。它允許組合多個(gè)轉移條件,這樣可以減少代價(jià)高昂的條件轉移的數量。表 3 列出了 PowerPC CR 邏輯指令。 表 3. PowerPC CR 邏輯指令 助記符 指令名 crand CR logical and crandc CR logical and with complement creqv CR logical equivalent crnand CR logical not and crnor CR logical not or cror CR logical or crorc CR logical or with complement crxor CR logical xor 整數運算指令 很多指令用于執行運算操作,包括 add、substract、negate、compare、multiply 和 divide。很多格式用于立即值、溢出檢測以及進(jìn)位和借位。各實(shí)現中 multiply 和 divide 的執行是不同的,因為這些通常是多周期指令。表 4 列出了 PowerPC 整數運算指令。 表 4. PowerPC 整數運算指令 助記符 指令名 add[o][.] add [& record OV] [& record CR0] addc[o][.] add carrying [& record OV] [& record CR0] adde[o][.] add extended [& record OV] [& record CR0] addi add immediate addis add immediate shifted addic[.] add immediate carrying [& record CR0] addme[o][.] add to minus one [& record OV] [& record CR0] addze[o][.] add to zero [& record OV] [& record CR0] divd[o][.] divide doubleword [& record OV] [& record CR0] divdu[o][.] divide doubleword unsigned [& record OV] [& record CR0] divw[o][.] divide word [& record OV] [& record CR0] divwu[o][.] divide word unsigned [& record OV] [& record CR0] mulhd[.] multiply high doubleword [& record CR0] mulhdu[.] multiply high doubleword unsigned [& record CR0] mulhw[.] multiply high word [& record CR0] mulhwu[.] multiply high word unsigned [& record CR0] mulld[o][.] multiply low doubleword [& record OV] [& record CR0] mulli multiply low immediate mullw[o][.] multiply low word [& record OV] [& record CR0] neg[o][.] negate [& record OV] [& record CR0] subf[o][.] subtract from [& record OV] [& record CR0] subfc[o][.] subtract from carrying [& record OV] [& record CR0] subfe[o][.] subtract from extended [& record OV] [& record CR0] subfi subtract from immediate subfis subtract from immediate shifted subfic[.] subtract from immediate carrying [& record CR0] subfme[o][.] subtract from to minus one [& record OV] [& record CR0] subfze[o][.] subtract from to zero [& record OV] [& record CR0] 邏輯、循環(huán)和移位指令 PowerPC 提供了一組完整的邏輯操作(指令),還支持對符號的擴展以及對 GPR 中前置零的統計。表 5 列出了 PowerPC 邏輯指令。 表 5. PowerPC 邏輯指令 助記符 指令名 and[.] and [& record CR0] andc[.] and with complement [& record CR0] andi. and immediate & record CR0 andis. and immediate shifted & record CR0 eqv[.] equivalent [& record CR0] nand[.] not and [& record CR0] nor[.] not or [& record CR0] or[.] or [& record CR0] orc[.] or with complement [& record CR0] oris or immediate shifted ori or immediate xor[.] xor [& record CR0] xoris xor immediate shifted xori xor immediate cntlzd[.] count leading zeros doubleword [& record CR0] cntlzw[.] count leading zeros word [& record CR0] extsb[.] extend sign byte [& record CR0] extsh[.] extend sign halfword [& record CR0] extsw[.] extend sign word [& record CR0] PowerPC 提供了一組健壯而強大的循環(huán)和移位操作(指令),如表 6 所列。 表 6. PowerPC 循環(huán)和移位指令 助記符 指令名 rldc[.] rotate left doubleword then clear [& record CR0] rldcl[.] rotate left doubleword then clear left [& record CR0] rldcr[.] rotate left doubleword then clear right [& record CR0] rldicl[.] rotate left doubleword immediate then clear left [& record CR0] rldicr[.] rotate left doubleword immediate then clear right [& record CR0] rldimi[.] rotate left doubleword immediate then mask insert [& record CR0] rlwimi[.] rotate left word immediate then mask insert [& record CR0] rlwinm[.] rotate left word immediate then and with mask [& record CR0] rlwnm[.] rotate left word then and with mask [& record CR0] sld[.] shift left doubleword [& record CR0] slw[.] shift left word [& record CR0] srad[.] shift right doubleword [& record CR0] sradi[.] shift right doubleword immediate [& record CR0] sraw[.] shift right word [& record CR0] srawi[.] shift right word immediate [& record CR0] srd[.] shift right doubleword [& record CR0] srw[.] shift right word [& record CR0] 浮點(diǎn)指令 PowerPC 提供了一組健壯的浮點(diǎn)運算、比較和轉換操作(指令)。與軟件支持一道,PowerPC 浮點(diǎn)運算完全符合 ANSI/IEEE 標準 754-1985 規范。在所有運算和比較操作中都支持單精度和雙精度浮點(diǎn)格式。 雖然浮點(diǎn)數以雙精度格式存儲于 FPR 中,但是,有一組單精度運算指令,可以執行運算操作并將最終結果舍入為單精度,同時(shí)檢測進(jìn)行單精度操作時(shí)可能會(huì )發(fā)生的異常(比如指數溢出、下溢和失去精度)。 * 一組 Load Floating-point Single指令可以訪(fǎng)問(wèn)存儲器中的字,并在將其放入目標 FPR 前把單精度值轉換為雙精度值。 * 一組 Store Floating-point Single指令可以將源 FPR 中的源操作數在存儲到存儲器中目標字之前轉換為單精度格式。 可以啟用或禁用具體種類(lèi)的浮點(diǎn)異常來(lái)支持設陷(trapping) 環(huán)境。表 7 列出了基本的和可選的 PowerPC 浮點(diǎn)指令集。 表 7. PowerPC 浮點(diǎn)指令 助記符 指令名 fmr[.] FP move [& record CR1] fneg[.] FP negate [& record CR1] fabs[.] FP absolute value [& record CR1] fnabs[.] FP negative absolute value [& record CR1] fadd[s][.] FP add [single] [& record CR1] fsub[s][.] FP subtract [single] [& record CR1] fmul[s][.] FP multiply [single] [& record CR1] fdiv[s][.] FP divide [single] [& record CR1] fsqrt[s][.] FP square root [single] [& record CR1] fmadd[s][.] FP multiply-add [single] [& record CR1] fmsub[s][.] FP multiply-subtract [single] [& record CR1] fnmadd[s][.] FP negative multiply-add [single] [& record CR1] fnmsub[s][.] FP negative multiply-subtract [single] [& record CR1] fcmpo FP compare ordered fcmpu FP compare unordered fsel[.] FP select [& record CR1] frsp[.] FP round to single [& record CR1] fcfid[.] FP convert from integer doubleword [& record CR1] fctid[z][.] FP convert to integer doubleword [& round to zero] [& record CR1] fctiw[z][.] FP convert to integer word [& round to zero] [& record CR1] fres[.] FP reciprocal estimate single [& record CR1] frsqrte[.] FP reciprocal square root estimate [& record CR1] FPSCR 處理指令 表 8 列出了基本的 PowerPC FPSCR 處理指令集。 表 8. PowerPC FPSCR 處理指令集 助記符 指令名 mcrfs move to CR from FPSCR mffs[.] move from FPSCR mtfsb0[.] move to FPSCR bit 0 mtfsb1[.] move to FPSCR bit 1 mtfsf[.] move to FPSCR field mtfsfi[.] move to FPSCR field immediate 加載和存儲指令 所有加載和存儲指令的執行都使用 GPR 或者 GPR 和指令中的立即字段作為存儲器訪(fǎng)問(wèn)的地址說(shuō)明符。用指令生成的數據有效地址來(lái)更新基址寄存器(也就是 RA)是大部分加載和存儲指令的一個(gè)可選項。 有用于以下方面的指令: * 字節、半字、字和雙字大小。 * 在 GPR 或 FPR 與存儲器之間移動(dòng)數據。 * 在 GPR 或 FPR 與存儲器之間移動(dòng)數據。 特殊的存儲器訪(fǎng)問(wèn)指令包括: * 多字加載/存儲 即 lmw 和 stmw ,可以操作最多 31 個(gè) 32 位字。 * 字符串指令 這些指令可以操作最長(cháng) 128 字節的字符串。 * 內存同步指令 這些用于實(shí)現內存同步。CR 的第 2 位(EQ 位) 設置用來(lái)記錄存儲操作的成功完成。內存同步指令包括: o lwarx (加載字并預留變址) o ldarx (加載雙字并預留變址) o stwcx (存儲字條件變址) o stdcx (存儲雙字條件變址) lwarx / ldarx 執行加載并設置處理器內部的預留位,編程模型不必明確了解這些行為。如果設置了預留位,相應的存儲指令 stwcx. / stdcx. 執行條件存儲,并清除預留位。 棧 PowerPC 體系結構沒(méi)有關(guān)于本地存儲器的棧的概念。體系結構沒(méi)有定義壓入或者彈出指令,也沒(méi)有定義專(zhuān)門(mén)的棧指針寄存器。不過(guò),有一個(gè)軟件標準可用于 C/C++ 程序,這個(gè)標準叫做嵌入式應用程序二進(jìn)制接口( Embedded Application Binary Interface,EABI),它定義了棧寄存器和內存的約定。EABI 將 GPR1 預留為棧指針,GPR3 到 GPR7 用于函數參數傳遞,GPR3 用于函數返回值。 需要為 C/C++ 提供接口的匯編語(yǔ)言程序必須遵循同樣的標準來(lái)保持約定。 高速緩存管理指令 PowerPC 體系結構包含了面向應用級高速緩存訪(fǎng)問(wèn)的高速緩存管理指令。高速緩存指令在表 9 中列出。 表 9. 高速緩存管理指令 助記符 指令名 dcbf Flush Data Cache Line dcbst Store Data Cache Line dcbt Touch Data Cache Line(for load) dcbtst Touch Data Cache Line(for store) dcbz Zero Data Cache Line icbi Invalidate Instruction Cache Line 當將高速緩存處理代碼移植到不同的 PowerPC 實(shí)現時(shí)要當心。雖然高速緩存指令可能是跨不同實(shí)現而通用的,高速緩存的組織和大小可能會(huì )有變化。例如,假定高速緩存大小以對其進(jìn)行刷新的代碼,在用于其他大小的高速緩存時(shí)可能需要進(jìn)行修改。而且,各實(shí)現的高速緩存初始化可能不同。有一些實(shí)現提供了自動(dòng)清除高速緩存標簽的硬件,而其他實(shí)現需要使用軟件循環(huán)來(lái)使高速緩存標簽無(wú)效。 自修改代碼 雖然編寫(xiě)自修改代碼不是一個(gè)工業(yè)標準,但有些情況下它是必不可少的。下面的序列介紹了執行代碼修改用到的指令: 1. 存儲修改的指令。 2. 執行 dcbst 指令,強制包含有修改過(guò)的指令的高速緩存行進(jìn)行存儲。 3. 執行 sync 指令,確保 dcbst 完成。 4. 執行 icbi 指令,使將要存放修改后指令的指令高速緩存行無(wú)效。 5. 執行 isync 指令,清除所有指令的指令管道,那些指令在高速緩存行被設為無(wú)效之前可能早已被取走了。 6. 現在可以運行修改后的指令了。當取這個(gè)指令時(shí)會(huì )發(fā)生指令高速緩存失敗,結果就會(huì )從存儲器中取得修改后的指令。 回頁(yè)首 計時(shí)器 大部分實(shí)現都提供了一個(gè) 64 位時(shí)基,可以通過(guò)兩個(gè) 32 位寄存器讀取,或者通過(guò)一個(gè) 64 位寄存器讀取。各實(shí)現的計時(shí)器增量不同,SPR 數和訪(fǎng)問(wèn)時(shí)基的指令也不同。所以,跨實(shí)現移植計時(shí)器代碼時(shí)要當心。另外的計時(shí)器可能也不同,但大多數實(shí)現都提供了至少一種遞減的可編程計時(shí)器。 回頁(yè)首 保持代碼的兼容性 需要在多個(gè)實(shí)現上進(jìn)行編程的 PowerPC 用戶(hù)通常會(huì )問(wèn)及保持代碼兼容性的技巧。下面的建議將有助于盡量減少移植問(wèn)題: * 盡可能使用 C 代碼。 當今的 C 編譯器在很多情況下可以生成與直接手寫(xiě)的匯編代碼在性能上相當的代碼。作為 Book I 代碼,C 代碼將保證代碼的兼容性。 * 盡可能避免使用處理器相關(guān)的匯編指令。 盡量不要在 C 中嵌入處理器相關(guān)的匯編指令,因為它們將更難被發(fā)現。分離開(kāi)那些已知會(huì )包含設備相關(guān)寄存器或指令的代碼。這些通常是啟動(dòng)次序和設備驅動(dòng)程序,不過(guò)也可能包括浮點(diǎn)代碼(包括 long long 類(lèi)型)。保持假定和依賴(lài)全部歸檔。 * 使用處理器版本寄存器(PVR),但只在適當的時(shí)候用。 跨差別較小的實(shí)現的通用代碼還好,PVR 可以用于做出判斷。但是,在需要進(jìn)行較大修改的情況下(例如,PowerPC AS 相對于 Book E MMU 代碼),建議使用單獨的代碼庫(code base)。 結束語(yǔ) PowerPC AS 和 PowerPC 都支持最初的 PowerPC 體系結構中定義的應用級基礎設施,同時(shí)為它們的具體目標市場(chǎng)提供了最佳的優(yōu)化。 就其兩種操作模式之一而言,PowerPC AS 實(shí)質(zhì)上與最初的 PowerPC 相同,而 PowerPC Book E 在它的 Book III 級別的定義中,已經(jīng)走向了不同的方向,為低價(jià)格、低功率以及體系結構靈活的嵌入式應用進(jìn)行了最優(yōu)化。當然,在 32 位的實(shí)現上還不能用雙字整數指令,在大部分嵌入式實(shí)現中浮點(diǎn)指令也只是通過(guò)軟件仿真提供支持。 不過(guò),這對應用程序二進(jìn)制在 PowerPC 體系結構家族樹(shù)的分支中自由地遷移來(lái)說(shuō)是一個(gè)非常有意義的機會(huì )。 回頁(yè)首 參考資料 * 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文. * PowerPC 體系結構分為三個(gè)級別(或“books”)以保持跨應用的兼容性。在 PowerPC Architecture Book中查找所有的書(shū)籍以及另外的資料。 * 要了解 IBM POWER 相關(guān)芯片制造的全部歷史,請閱讀“ 人類(lèi)的 POWER:IBM 的芯片制造歷史”( developerWorks, 2004 年 3 月)。 * 在 IBM PowerPC站點(diǎn)查找更多資料。 * 在 IBM PowerPC Web 站點(diǎn)技術(shù)庫可以得到具有詳細技術(shù)資料的用戶(hù)手冊。您還可以在專(zhuān)門(mén)的 PowerPC Product Briefs和 PPC 白皮書(shū)中找到有價(jià)值的資料。 * 就其兩種操作模式之一而言, PowerPC AS實(shí)質(zhì)上與最初的 PowerPC 相同,而 PowerPC Book E為嵌入式市場(chǎng)而做了最優(yōu)化。 * “ PowerPC 匯編”( developerWorks, 2002 年 7 月) 從 PowerPC 的角度概要介紹了匯編語(yǔ)言,并對比了三種體系結構的例子。 * “ A programmer's view of performance monitoring in the PowerPC microprocessor”( IBM Systems Journal, 1997)教您如何使用 PowerPC 芯片上的性能監控器(Performance Monitor,PM)來(lái)分析不同工作負荷下的處理器、軟件和系統屬性。 * PowerPC Performance Libraries Project 為 IBM PowerPC 4xx 嵌入式處理器提供了許多優(yōu)化的庫函數。這些庫涵蓋了浮點(diǎn)仿真、常見(jiàn)的 C 庫字符串和內存函數。 * PMAPI 是一個(gè)庫,它有一組 API,可以訪(fǎng)問(wèn)所選的 IBM POWERPC 微處理器所包含的硬件性能計數器。 * PowerPC 體系結構是 精減指令集計算機(RISC)體系結構。 * 要查找 iSeries、pSeries 和其他基于 POWER 的平臺的軟件和文獻, developerWorks 的 Linux on POWER 開(kāi)發(fā)者參考資料和下載頁(yè)是極好的出發(fā)點(diǎn)。 * IBM 的 Linux on PowerPC 團隊的目標是改進(jìn)和擴展用于嵌入式、32 位和 64 位處理器的 Linux。要獲得兼容性的信息、文檔、代碼或者更多,請訪(fǎng)問(wèn) Linux on PowerPC 主頁(yè)。 * IBM 的 Linux Technology Center 提供了 POWER 程序員參考資料匯編。 * Linux on POWER概要介紹了來(lái)自 IBM 的 POWER 相關(guān)的 Linux 產(chǎn)品。 * 在 developerWorks Linux 專(zhuān)區可以找到更多為 Linux 開(kāi)發(fā)人員準備的參考資料。 * 在 Developer Bookstore 的 Linux 區可以找到很多精選的 Linux 書(shū)籍。 |
| 1. 概述 Book E 定義的 PowerPC 指令集的指令可分為以下幾類(lèi): 分支跳轉指令 CR 指令 整數指令 浮點(diǎn)指令 處理器控制指令 存儲管理相關(guān)指令 CR 指令主要是對 CR 內部位運算支持的一些指令,如 crand, cror, crxor 等等。 2. 常用指令 先看一個(gè)測試程序: ------------------------------------------------------------------ int test_call(int a, int b, int c) { a = b + c; return a; } int test_if(int s) { int i; if(s > 0) i = s; else if(s < 0) i = -s; else i = s * 8; return i; } int test_cyc1(int c) { int sum = 0; do { sum += c; c--; } while(c > 0); return c; } int test_cyc2(int c) { int sum = 0; for(; c > 0; c--) sum += c; return c; } int main() { int a, b, c, d; a = test_if(5); b = test_cyc1(10); c = test_cyc2(10); d = test_call(1, 2, 3); return a + b + c + d; } ------------------------------------------------------------------ 引入的目的在于查看判斷、循環(huán)和過(guò)程調用這些基本結構在 PowerPC 里怎么被支持。 -O2 參數編譯后,objdump -S -d 反匯編,則: ------------------------------------------------------------------ 1000040c <test_call>: int test_call(int a, int b, int c) { a = b + c; return a; } 1000040c: 7c 64 2a 14 add r3,r4,r5 ----> 對應 a, b, c 三個(gè)參數,同時(shí) r3 又置返回值 10000410: 4e 80 00 20 blr ----> 跳轉到 LR 所存放的地址處,即函數返回 10000414 <test_if>: int test_if(int s) { int i; if(s > 0) 10000414: 7c 60 1b 79 mr. r0,r3 -----> r3 移到 r0,若 r0 小于、大于、等于 0,則置 CR0 的相應位。指令后多一點(diǎn),則說(shuō)明該指令會(huì )據執行結果,設置 CR 的相應位 10000418: 7c 03 03 78 mr r3,r0 -----> 此條指令多余 1000041c: 4d a1 00 20 bgtlr+ -----> 若 CR0[gt] 位為 1,則跳轉到 LR 所存放的地址處,即直接函數返回了。此條指令等價(jià)于 bclr 13, 1 i = s; else if(s < 0) 10000420: 38 60 00 00 li r3,0 10000424: 4d 82 00 20 beqlr -----> 若 CR0[eq] 位為 1,則跳轉到 LR 所存放的地址處,也直接函數返回了。此條指令等價(jià)于 bclr 12, 2 i = -s; 10000428: 7c 60 00 d0 neg r3,r0 -----> r0 取反,入 r3 else i = s * 8; return i; } 1000042c: 4e 80 00 20 blr -----> 跳轉到 LR 所存放的地址處,函數返回 10000430 <test_cyc1>: int test_cyc1(int c) { 10000430: 34 03 ff ff addic. r0,r3,-1 10000434: 7c 69 03 a6 mtctr r3 10000438: 41 80 00 10 blt- 10000448 <test_cyc1+0x18> int sum = 0; do { sum += c; c--; 1000043c: 38 63 ff ff addi r3,r3,-1 } while(c > 0); 10000440: 42 00 ff fc bdnz+ 1000043c <test_cyc1+0xc> return c; } 10000444: 4e 80 00 20 blr 10000448: 38 00 00 01 li r0,1 1000044c: 7c 09 03 a6 mtctr r0 10000450: 4b ff ff ec b 1000043c <test_cyc1+0xc> 10000454 <test_cyc2>: int test_cyc2(int c) { 10000454: 2c 03 00 00 cmpwi r3,0 10000458: 39 20 00 00 li r9,0 1000045c: 7d 23 48 1e .long 0x7d23481e int sum = 0; for(; c > 0; c--) sum += c; return c; } 10000460: 7d 23 4b 78 mr r3,r9 10000464: 4e 80 00 20 blr int main() { 10000468: 94 21 ff e0 stwu r1,-32(r1) 1000046c: 7c 08 02 a6 mflr r0 int a, b, c, d; a = test_if(5); 10000470: 38 60 00 05 li r3,5 10000474: 90 01 00 24 stw r0,36(r1) 10000478: 93 61 00 0c stw r27,12(r1) 1000047c: 93 81 00 10 stw r28,16(r1) 10000480: 93 a1 00 14 stw r29,20(r1) 10000484: 4b ff ff 91 bl 10000414 <test_if> 10000488: 7c 7d 1b 78 mr r29,r3 b = test_cyc1(10); 1000048c: 38 60 00 0a li r3,10 10000490: 4b ff ff a1 bl 10000430 <test_cyc1> 10000494: 7c 7b 1b 78 mr r27,r3 c = test_cyc2(10); 10000498: 38 60 00 0a li r3,10 d = test_call(1, 2, 3); 1000049c: 7f bd da 14 add r29,r29,r27 100004a0: 4b ff ff b5 bl 10000454 <test_cyc2> 100004a4: 38 80 00 02 li r4,2 100004a8: 7c 7c 1b 78 mr r28,r3 100004ac: 38 a0 00 03 li r5,3 100004b0: 38 60 00 01 li r3,1 100004b4: 4b ff ff 59 bl 1000040c <test_call> return a + b + c + d; } 100004b8: 80 01 00 24 lwz r0,36(r1) 100004bc: 7f 9c 1a 14 add r28,r28,r3 100004c0: 83 61 00 0c lwz r27,12(r1) 100004c4: 7c 7d e2 14 add r3,r29,r28 100004c8: 83 81 00 10 lwz r28,16(r1) 100004cc: 83 a1 00 14 lwz r29,20(r1) 100004d0: 7c 08 03 a6 mtlr r0 100004d4: 38 21 00 20 addi r1,r1,32 100004d8: 4e 80 00 20 blr ------------------------------------------------------------------ 3. 分類(lèi)概述 3.1 分支跳轉指令 這類(lèi)指令算是 PowerPC 里比較有特色的,也是稍顯復雜的。這類(lèi)指令與 CR, LR 和 CTR 緊密相聯(lián),建構起判斷、循環(huán)和過(guò)程調用這些程序的基本結構。其大致可分為四類(lèi): Branch Branch Conditional Branch Conditional to Count Register Branch Conditional to Link Register 3.1.1 Branch 這類(lèi)指令與 CR 沒(méi)有聯(lián)系,即為非條件跳轉,助記符后直接跟立即數地址。指令內為立即數地址預留 26 位,即可跳轉 2^26 大小的空間,如:(CIA, Current Instruction Address) b 0x20 -----> 以當前指令地址為基點(diǎn),往后跳轉 0x20 字節,即 PC = CIA + 0x20 ba 0x20 -----> 直接跳轉到地址 0x20 處。后綴為 a,則表示使用 Absolute Address,PC = 0x20。 bl 0x20 -----> 在 b 0x20 的基礎上,將 LR 更新為 CIA + 4 bla 0x20 -----> 使用絕對地址,且更新 LR。后綴帶 l,則表示更新 LR 為 CIA + 4 以上針對 32 位的情形,對 64 位則使用指令 be, bea, bel, bela 功能與上同。 3.1.2 Branch Conditional 此類(lèi)為條件跳轉指令。皆以 bc 開(kāi)頭,帶 3 個(gè)操作數,如: bc BO, BI, BD bca BO, BI, BD bcl BO, BI, BD bcla BO, BI, BD 后綴 a, l 的含義與 branch 類(lèi)指令同。BO 指定跳轉的條件,5 位;BI 指定關(guān)聯(lián)的 CR 位,也是 5 位;BD 為跳轉的立即數地址,16 位。 其中以 BO 的編碼最為復雜(BO 從左到右編號為 0 ~ 4): BO[0]: 為 1,則直接跳轉 BO[1]: 為 1,則條件為真時(shí),跳轉。否則條件為假時(shí),跳轉 BO[2]: 為 1,則 CTR 不自動(dòng)減 1 BO[3]: 為 1 時(shí),則 CTR == 0 時(shí)跳轉;為 0 時(shí),則 CTR != 0 時(shí)跳轉 BO[4]: 靜態(tài)預測位,1 表示 unlikely,0 表示 likely 則常見(jiàn)的 BO 值: 20 (0b10100) 則表示無(wú)條件跳轉 12 (0b01100) 則表示 CR 的某個(gè)位為 1 時(shí)跳轉 4 (0b00100) 則表示 CR 的某個(gè)位為 0 時(shí)跳轉 至于靜態(tài)預測的策略位,默認被置為 0,則其行為為: b1. 目標地址小于當前指令地址,預測為跳轉 b2. 目標地址大于當前指令地址,預測為不跳轉 b3. 對于目標地址在 CTR/LR 中的條件跳轉指令,一律預測為不跳轉 若該位被置 1,則上述 b1, b2, b3 的靜態(tài)預測行為分別為:不跳轉,跳轉,跳轉。 可以給分支指令加一個(gè) +/- 的后綴,來(lái)簡(jiǎn)化。加 '+' 的指令,一律預測為跳轉。加 '-' 的分支指令,一律預測為不跳轉。 則對于 b1,后綴 '+' 會(huì )將 y 位置 0,'-' 則將 y 位置 1。 對于 b2,后綴 '+' 會(huì )將 y 位置 1,'-' 則將 y 位置 0。 對于 b3,后綴 '+' 會(huì )將 y 位置 1,'-' 則將 y 位置 0。 BI 與關(guān)聯(lián) CR 位的關(guān)系為: 32 + BI 即,若 BI 為 2,則對應于 CR[34],即為 CR0[gt] 位。 以上針對 32 位的情形,對 64 位則使用指令 bce, bcea, bcel, bcela 功能與上同。 3.1.3 Branch Conditional to Count Register bcctr BO, BI bcctrl BO, BI 后綴 l 的含義與 branch 類(lèi)指令同。 BO,BI 的編碼與 Branch Conditional 類(lèi)指令同。 跳轉目標地址位于 CTR 中。 以上針對 32 位的情形,對 64 位則使用指令 bcctre, bcctrel 功能與上同。 3.1.4 Branch Conditional to Link Register bclr BO, BI bclrl BO, BI 后綴 l 的含義與 branch 類(lèi)指令同。 BO,BI 的編碼與 Branch Conditional 類(lèi)指令同。 跳轉目標地址位于 LR 中。 以上針對 32 位的情形,對 64 位則使用指令 bclre, bclrel 功能與上同。 3.2 CR 指令 這類(lèi)指令包括用來(lái)支持 CR 內部位運算的指令和 CR 與 GPR 之間的數據交換指令。 3.2.1 CR 內位運算指令 這類(lèi)指令的格式皆為: crxxx BT, BA, BB BT, BA, BB 是 CR 內的位編號,取值范圍為 0 ~ 31,如 crand 0, 8, 12,則將 CR[32+8] (CR2[lt]) 與 CR[32+12] (CR3[lt]) 作與操作后,將結果置入 CR[32+0] (CR0[lt]),即 CR[32] = CR[40] & CR[44] crand: CR[32+BA] & CR[32+BB] crandc: CR[32+BA] & (~CR[32+BB]) creqv: ~(CR[32+BA] ^ CR[32+BB]),即位相等,則置 1;不等則置 0 crnand: ~(CR[32+BA] & CR[32+BB]) crnor: ~(CR[32+BA] | CR[32+BB]) cror: CR[32+BA] | CR[32+BB] crorc: CR[32+BA] | (~CR[32+BB]),先取反后再或 crxor: CR[32+BA] ^ CR[32+BB],位異或 3.2.2 CR 與 GPR 間數據交換指令 3.2.2.1 mcrf BF, BFA --- Move Condition Register Fields 將 CR 之 BFA 域復制到 BF 域。如 mcrf 0, 3 則將 CR3 拷入 CR0 3.2.2.2 mtcrf FXM, RS --- Move To Condition Register Fields 通用寄存器 RS 之 32 ~ 63 位以 4 位為單位,對應于 CR 的 8 個(gè)域,編號為 RS0 ~ RS7; FXM 為域掩碼,8 位,從左到右編號為 0 ~ 7,對應于 RS、CR 的 8 個(gè)域。某位為 1,則將對應的 RS 域拷貝到對應的 CR 域中。 若 FXM 為 0x80,則只將 CR0 = RS0 若 FXM 為 0xc8,則將 CR0 = RS0, CR1 = RS1, CR4 = RS4 3.2.2.3 mfcr RT --- Move From Condition Register 將 CR 的內容移入通用寄存器 RT 的 32 ~ 63 位。 3.3 整數指令 這類(lèi)指令大致分為如下幾類(lèi): 整數訪(fǎng)存指令 整數算術(shù)運算指令 整數邏輯運算指令 整數比較指令 整數陷阱指令 整數移位指令 XER 指令 其中以整數循環(huán)移位指令最為特別。 3.3.1 整數訪(fǎng)存指令 3.3.1.1 Load Byte/Half-word/Word and Zero 該類(lèi)指令從指定地址處讀取 8 位、16 位、32 位數據,置入 RT,RT 高位置 0 lbz/lbzu RT, D(RA) lbzx/lbzux RT, RA, RB lhz/lhzu RT, D(RA) lhzx/lhzux RT, RA, RB lwz/lwzu RT, D(RA) lwzx/lwzux RT, RA, RB RT, RA, RB 皆為 GPR,D 為有符號立即數。則有效地址的計算分別為:RA[32:63] + D,RA[32:63] + RB[32:63],有效地址高 32 位置 0。 后綴 u 表示 Update,即將有效地址更新到 RT 中 后綴 x 表示 Indexed,即使用 RA + RB 的尋址方式 以上用于 32 位,對 64 位,上述指令皆加后綴 'e'。則有效地址的 0 ~ 31 位, 不再置 0,其計算方式如下:RA + D,RA + RB。 此外,用于 64 位的還有對雙字操作的支持: lde/ldue/ldxe/lduxe 3.3.1.2 Load Half-word Algebraic lha/lhau RT, D(RA) lhax/lhaux RT, RA, RB 與 lhz 不同的是,該指令將所讀取的半字的最高位 (RT[48]) 填充到 RT[32:47],實(shí)際上就是形成一個(gè) 16 位的補碼有符號數。 有效地址計算與上同;后綴 u, x 與上同。 對 64 位情形,上述指令皆加后綴 'e',有效地址計算與上小節同。 3.3.1.3 Load Halfword/Word Byte-Reverse 從指定地址處讀取 16 位/32 位數據,將字節反轉后置入 RT,RT 高位置 0 lhbrx RT, RA, RB lwbrx RT, RA, RB 如: lwbrx r3, r2, r1,若 r2 + r1 地址處的數據為 0x55aa66bb,則 r3 的結果為 0xbb66aa55 對 64 位情形,上述指令皆加后綴 'e',有效地址計算與上小節同。 3.3.1.4 Load Multiple Word lmw RT, D(RA) 該指令將 RA + D 開(kāi)始處的數據,順序置入 RT ~ R31 中,共讀取 31 - T 個(gè)字 該指令無(wú) 64 位擴展。 3.3.1.5 Load String Word lswi RT, RA, NB (后綴 i,表示立即數 Immediate) lswx RT, RA, RB (后綴 x,表示 Indexed 尋址方式) 加載 n 個(gè)字節到 RT 開(kāi)始的寄存器中; 當 NB == 0 時(shí) n = 32; NB != 0 時(shí) n = NB,NB 取值范圍為 0 ~ 31 如 r3 = 0x1000 : lswi r4, r3, 16 則將 0x1000 處的 16 字節,依次寫(xiě)入 r4, r5, r6, r7 對于 lswx,要加載的字節數則位于 XER[57:63] 該指令無(wú) 64 位擴展。 3.3.1.6 Load Word/Doubleword and Reserve lwarx RT, RA, RB 該指令與 lwzx 的差別在于,其還將處理器內部的 RESERVE 位置為 1,并將有效地址對應的物理地址放入 RESERVE_ADDR 中。 該指令的 64 位版本為: lwarxe RT, RA, RB,差別還是在于有效地址的 0 ~ 31 不被置 0 此外還有一個(gè) ldarxe RT, RA, RB,與 lwarxe 的差別在于其加載 8 字節的數據。 這三條指令常分別與 stwcx./stwcxe./stdcxe. 聯(lián)用,用于實(shí)現鎖操作,類(lèi)似 MIPS 之 ll/sc 指令。 3.3.1.7 Store stb/stbu RS, D(RA) stbx/stbux RS, RA, RB sth/sthu RS, D(RA) sthx/sthux RS, RA, RB stw/stwu RS, D(RA) stwx/stwux RS, RA, RB 該類(lèi)指令將 RS 中的 8 位、16 位、32 位數據寫(xiě)入有效地址處。后綴 'u', 'x' 之含義與 3.3.1.1 同。 上述 12 條指令加后綴 'e' 則用于 64 位。有效地址計算與與 3.3.1.1 同。 另用于 64 位的還有對雙字操作的支持: stde/stdue/stdxe/stduxe 3.3.1.8 Store Halfword/Word Byte-Reverse sthbrx RS, RA, RB stwbrx RS, RA, RB 將 RS 中的 16/32 bit 的數據字節反轉后置入有效地址處。該指令用于支持在大端系統上以小端序存儲數據,亦或在小端系統上以大端序存儲數據。 對 64 位情形,上述指令皆加后綴 'e',有效地址計算與上小節同。 3.3.1.9 Store Multiple Word smw RS, D(RA) 該指令將 RS ~ R31 中的數據 (一個(gè)字),寫(xiě)入到 RA + D 處 該指令無(wú) 64 位擴展。 3.3.1.10 Store String Word stswi RS, RA, NB (后綴 i,表示立即數 Immediate) stswx RS, RA, RB (后綴 x,表示 Indexed 尋址方式) 與 lswi/lswx 的操作相反,其將 RS 開(kāi)始的寄存器組中的 n 個(gè)字節,寫(xiě)入到有效地址處(位于 RA) 當 NB == 0 時(shí) n = 32; NB != 0 時(shí) n = NB,NB 取值范圍為 0 ~ 31 如 r3 = 0x1000 : stswi r4, r3, 16 則將 r4, r5, r6, r7 中的 16 字節數據依次寫(xiě)入 0x1000 處 對于 stswx,要加載的字節數則位于 XER[57:63] 該指令無(wú) 64 位擴展。 3.3.1.11 Store Word/Doubleword Conditional stwcx. RS, RA, RB 如果 RESERVE 位為 1,且 RA + RB 對應的物理地址與 RESERVE_ADDR 一致,則將 RS[32:63] 的內容寫(xiě)入到 RA + RB 處,將 CR0[eq] 位置為 1 后,再將 RESERVE 位復位為 0。 若條件不滿(mǎn)足,則僅將 CR0[eq] 位置為 0 可用該指令與 lwarx 聯(lián)用,實(shí)現 spin_lock: li r0, 1 loop: lwarx r4, 0, r3 cmpwi r4, 0 # r4[32:63] 與 0 比較 bne loop stwcw. r0, 0, r3 bne loop isync 解鎖則為: msync li r0, 0 stw r0, 0(r3) 下面的指令用于 64 位: stwcxe. RS, RA, RB stdcxe. RS, RA, RB 差別在于有效地址的高 32 位不再被置為 0。 3.3.2 整數算術(shù)運算指令 3.3.3 整數邏輯運算指令 3.3.4 整數比較指令 cmp BF, L, RA, RB cmpi BF, L, RA, SI # RA 與有符號立即數 SI 比較 cmpl BF, L, RA, RB # RA, RB 邏輯比較。l ---> logical cmpli BF, L, RA, UI # RA 與無(wú)符號立即數 UI 邏輯比較 BF 取值 0 ~ 7,用于指定使用的 CR 域 L 為 0,則為 32 位比較;為 1,則為 64 位比較 如: cmpi 0, 0, r3, 5 若 r3 > 5,則 CR0[gt] = 1;若 r3 < 5,則 CR0[lt] = 1 3.3.5 整數陷阱指令 tw TO, RA, RB twi TO, RA, SI TO 為立即數,5 位,從左到右標號為 0 ~ 4,依次表示小于、大于、等于、無(wú)符號小于、無(wú)符號大于。用于指定 Trap 的條件。 SI: Signed Immediate 如: twi 0x10, r3, 5 則如果 r3 < 5,則陷入異常。 以上用于單字 (32 bit) 比較,雙字比較則用: td TO, RA, RB tdi TO, RA, SI 3.3.6 整數移位指令 3.3.6.1 Rotate rlwimi RA, RS, SH, MB, ME # Rotate Left Word Immediate then Mask Insert rlwinm RA, RS, SH, MB, ME # Rotate Left Word Immediate then AND with Mask rlwnm RA, RS, RB, MB, ME # Rotate Left Word then AND with Mask 以下是該指令的一些例子: all r11 is: 0x55aa67bb r0 = 0x00000000 rlwimi r0, r11, 8, 0, 31 r0 is: 0xaa67bb55 r0 = 0x12345678 rlwimi r0, r11, 8, 0, 14 r0 is: 0xaa665678 dst = 0x12345678 rlwimi r0, r11, 8, 28, 3 r0 is: 0xa2345675 r0 = 0x00000000 rlwinm r0, r11, 8, 0, 31 r0 is: 0xaa67bb55 r0 = 0x12345678 rlwinm r0, r11, 8, 0, 14 r0 is: 0xaa660000 rldcl rldcr rldic rldicl rldicr rldimi 3.3.6.2 Shift slw srw sraw srawi slw./srw./sraw./srawi. sld srd srad sradi 3.3.7 XER 指令 mcrxr BF mcrxr64 BF 3.4 浮點(diǎn)指令 這類(lèi)指令包括: 浮點(diǎn)數據加載與存儲指令 浮點(diǎn)運算指令 浮點(diǎn)數近似和轉化指令 浮點(diǎn)比較指令 浮點(diǎn)狀態(tài)和控制寄存器指令 有關(guān)該指令的詳情留待以后以《PowerPC 浮點(diǎn)結構》的形式討論吧。 3.5 處理器控制指令 這類(lèi)指令包括用于支持異常中斷處理的: sc System Call rfci Return From Critical Interrupt rfi Return From Interrup 用于處理器控制寄存器維護的: mfspr RT, SPRN Move From SPRN (Special Purpose Register) to RT mtspr SPRN, RS Move RS To SPRN mfdcr RT, DCRN Move From DCRN (Device Control Register) to RT mtdcr DCRN, RS Move RS To DCRN mfmsr RT Move From MSR to RT mtmsr RS Move RS To MSR wrtee RA Write MSR External Enable, MSR[EE] = RA[48] wrteei E Write MSR External Enable Immediate, MSR[EE] = E 以及用于指令同步的: isync 其保證在其之前的所有指令皆提交,在其自己被提交前,其之后的指令不會(huì )進(jìn)入流水線(xiàn) 3.6 存儲管理相關(guān)指令 這類(lèi)指令包括用于 TLB 管理的: tlbivax tlbre tlbwe tlbsx tlbsync tlbivaxe tlbsxe 用于 Cache 管理的: dcba/dcbf/dcbi/dcbst/dcbt/dcbtst/dctz/icbi/icbt dcbae/dcbfe/dcbie/dcbste/dcbte/dcbtste/dctze/icbie/icbte 用于存儲同步的: msync mbar |
| A. 以下取 Book E 之 ULR 精要 ULR (User Level Register) 即用戶(hù)態(tài)程序能用的寄存器,包括只讀的和可讀寫(xiě)的。 最常用的 ULR 包括以下寄存器: 1. GRP (General Purpose Register) 通用寄存器,即用于定點(diǎn)運算的寄存器,共 32 個(gè) 2. CR (Condition Register) 指令狀態(tài)寄存器,其格式如下所示: ![]() 注意:Book E 對寄存器的位編號與通常不同,因其支持 PowerPC 64,故其將 64 位寄存器從最高位 (MSB) 到最低位 (LSB) 編號為 0 ~ 63,32 位寄存器則編號為 32 ~ 63。 CR 以4位為單位分成 8 個(gè)域,每個(gè)域能描述 4 種狀態(tài)。 2.1 CR0 用于存放 RC 位為1 的整數指令執行后的狀態(tài)。CR[32:35] 依次表示小于、大于、等于和溢出。當指令執行的結果小于、大于或等于 0 時(shí)則置相應的CR[32:34] 的位;CR[35] 的值則直接復制自XER 的 SO (Summary Overflow)位。 2.2 CR1用于存放 RC 位為 1 的所有浮點(diǎn)指令執行后的浮點(diǎn)異常狀態(tài)。其內容直接復制于浮點(diǎn)狀態(tài)與控制寄存器 (FPSCR),CR[36:39] 依次對應于浮點(diǎn)異常 (FX)、浮點(diǎn)使能異常 (FEX)、浮點(diǎn)非法操作異常 (VX) 和浮點(diǎn)溢出異常 (OX)。 RC 位為 1 的指令,其助記符的最后有一個(gè) '.' ,如 addic./divw./mullw./neg./and./or./xor./nand./nor. 2.3 對于比較指令(整數和浮點(diǎn)),可以通過(guò)操作數 BF 指定比較結果所存儲的 CR 域: cmp 3, 0, r3, r4 (cmp BF, L, RA, RB) 操作數 L = 0,表示此為 32 位比較,即只比較 r3, r4 的 32 ~ 63 位。若 r3 > r4,則將 CR3[gt] (CR[45]) 置位。浮點(diǎn)比較類(lèi)似,但域內第 4 位含義與整數不同,整數依然表示溢出 (SO),且其值拷貝自 XER[SO];而對浮點(diǎn)比較,若該位被置,則表示某一浮點(diǎn)操作數不是數值。 2.4 此外 RC 位為 1 的條件存儲指令 (stwcx./stwcxe./stdcxe.),在存儲操作成功時(shí)置 CR0[2] (EQ 位) 為 1。 3. LR (Link Register) 鏈接寄存器,用于存放返回地址 Branch and Link 類(lèi)指令(如 bl,指令內 LK 位為 1)會(huì )將下條指令的地址自動(dòng)寫(xiě)入 LR。bl 用于調用子過(guò)程,則置入 LR 的即為返回地址 Branch Conditional to Link Register 類(lèi)指令(如 bclr)則使用 LR 作為跳轉的目標地址,該類(lèi)指令通常用于子過(guò)程返回 4. CTR (Count Register) 計數寄存器,常用于存放跳轉目標地址,與 Branch Conditional to Count Register 類(lèi)指令配合使用;亦可存放循環(huán)變量與條件分支指令 (Branch Conditional) 配合,實(shí)現循環(huán) CR,LR 和 CTR 是與分支指令緊密聯(lián)系的,在實(shí)現基本程序結構之判斷、循環(huán)以及過(guò)程調用方面作用巨大。 5. XER (Integer eXception Register) 整數異常寄存器,用于置整數運算的溢出 (Overflow)、進(jìn)位 (Carry Out) 以及批量加載和存儲指令要操作的字節數 6. E500 ULR 下圖為 e500 之 ULR 概覽: ![]() 可以看到 e500 沒(méi)有浮點(diǎn)寄存器,其沒(méi)有浮點(diǎn)部件。 7. E600 ULR 下圖為 e600 之 ULR 概覽: ![]() e600 則含32個(gè)浮點(diǎn)寄存器,且含 32 個(gè)向量寄存器 (VR0 ~ VR31) 用于支持向量計算。 B. ABI ABI 即 Application Binary Interface。其主要規定通用寄存器的使用約定,以及過(guò)程調用的棧的組織。一般最常用的就是通用寄存器的使用約定。Linux 下常用SYS V ABI。 以下是比較諸多 PowerPC ABI 版本后的一個(gè)交集: GPR1: Stack Pointer GPR3 ~ GPR4: 參數1 ~ 2,同時(shí)復用之,置 2 個(gè)返回值 GPR5 ~ GPR10: 參數 3 ~ 8 e500 ABI 繼承于 System V ABI PowerPC Processor Supplement 以較為常用的 System V ABI 為準,其他寄存器的約定如下: GPR0: volatile, may be used by function linkage GPR2: reserved for system GPR11 ~ 12: volatile, may be used by function linkage GPR13: small data area pointer GPR14 ~ 31: saved C. Reference [1] Book E: Enhanced PowerPC Architecture, v1.0, 2002.7 [2] PowerPC e500 Core Family Reference Manual, Rev. 1, 2005.4 [3] e600 PowerPC Core Reference Manual, Rev. 0, 2006.3 [4] SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement (SYS V ABI), Rev. A, 1995.9 [5] PowerPC Embedded Application Binary Interface (EABI), v1.0, 1995.1 [6] PowerPC e500 Application Binary Interface User’s Guide, Rev. 1.0, 2003.3 |
| XFX-Form類(lèi)指令: 該類(lèi)指令主要包括mtspr,mfspr,mtcr,mfcr指令。主要用于訪(fǎng)問(wèn)SPR寄存器和CR寄存器。XFX-Form類(lèi)指令格式如下: 0-5 6-10 11-20 21-30 31 OPCD RT spr/tbr XO - XO-Form類(lèi)指令: 該類(lèi)指令主要用來(lái)支持帶進(jìn)位的算術(shù)運算和乘除指令,指令格式如下: 0-5 6-10 11-15 16-20 21 22-30 31 OPCD RT RA RB OE XO Rc 主要指令有: addo.,subfo.,addco.,subfco.,除了影響CA,SO,OV位和CR0字段外,還可以將CA位參與加減運算 addeo.,subfeo.,addzeo.,subfzeo., 除了影響CA,SO,OV位和CR0字段外,還可以將CA位參與加減運算 mullw,divw,用作乘除運算 M-Form類(lèi)指令: 該指令主要作用是對選定的字段循環(huán)左移并做一些相應的掩碼操作。指令格式如下: 0-5 6-10 11-15 16-20 21-25 26-30 31 OPCD RS RA SH MB ME Rc 最常用的指令是rlwimi RA,RS,RH,MB,ME,功能描述如下: 首先將存放在RS中的值循環(huán)左移SH位,將結果賦予r。 然后,用MASK計算掩碼m,MASK(MB+32,ME+32)表示將一個(gè)數據中的第MB+32——ME+32字段置1,其他字段置0,然后賦予m。 如果ME小于MB,則將ME+32和MB+32之間(不含ME+32,MB+32)字段置0,其他置1。 最后將r&m|(RA)&(!m)的結果賦予RA。 還有一條重要指令是rlwinm,區別在于最后將RA寄存器賦值為r&m。該指令的主要作用就是從RS寄存器中提取一個(gè)字段,然后放到RA寄存器中。 到這里,關(guān)于PowerPC指令集的部分就介紹完了。加上前面的文章,基本上涵蓋了PowerPC的寄存器,ABI和指令集,都是處理器中比較核心得到部分。后面的文章主要介紹中斷處理,內存管理等內容。 |
| 在E500內核中,中斷處理器正常執行流的事件有兩種——異常和中斷。異常是由E500內核內部產(chǎn)生的,比如TLB miss之類(lèi)的事件;而中斷是通過(guò)處理器的外部引腳產(chǎn)生的。其實(shí),中斷本身就是異常的一種。 E500的外部中斷可以通過(guò)3個(gè)信號產(chǎn)生#int,#cint和#mcp,分別代表中斷,critical中斷和Machine Check中斷。 #int信號有效時(shí),表示外部中斷事件發(fā)生。這些中斷來(lái)自于外部中斷控制器(PIC)。當MSR寄存器的EE位為1且#int信號有效時(shí),E500內核將處理這些外部中斷。 #cint信號有效時(shí),表示critical中斷發(fā)生。與#int的中斷源一樣,都是來(lái)自于外部中斷控制器。當MSR寄存器的CE位為1且#cint信號有效時(shí),E500內核將處理critical中斷。 #mcp出現上升沿時(shí),表示Machine Check事件發(fā)生。當MSR寄存器的ME位為1且#mcp為上升沿時(shí),E500將處理Machine Check事件。 E500內核異常的分類(lèi)及優(yōu)先級如下: 1. HRESET。E500內核中沒(méi)有為復位異常安排專(zhuān)門(mén)的中斷向量。但是,E500的復位起始地址是0xFFFFFFFC,也可以算是復位異常的向量地址。這個(gè)處理有點(diǎn)像MIPS的復位,MIPS復位起始地址是在0xBFC00000。 2. Machine Check。比如Cache的奇偶校驗引發(fā)的事件就算此類(lèi)異常。 3. Critical Interrupt。前面已經(jīng)提過(guò)了。 4. Debug Interrupt。與critical中斷共享異常向量,用于系統調試。當MSR寄存器的DE位為1時(shí)有效。 5. External Interrupt。前面已介紹。 6. ITLB MISS。當處理器取指時(shí),如果訪(fǎng)問(wèn)指令的地址沒(méi)有在TLB中命中時(shí)產(chǎn)生此異常。 7. ISI。在用戶(hù)模式訪(fǎng)問(wèn)內核模式下才能訪(fǎng)問(wèn)的內存空間,以及因為指令預取部件訪(fǎng)問(wèn)的字節序與定義的字節序不一致時(shí)引發(fā)此異常。 8. Program。執行非法指令,在用戶(hù)模式下執行內核模式才能執行的指令或者tw指令條件滿(mǎn)足時(shí),產(chǎn)生此異常。 9. DTLB MISS。讀取數據時(shí),如果訪(fǎng)問(wèn)的數據地址沒(méi)有在TLB中命中時(shí)產(chǎn)生此異常。 10. DSI。用戶(hù)模式下訪(fǎng)問(wèn)內核模式才能訪(fǎng)問(wèn)的內存空間,或者數據訪(fǎng)問(wèn)的字節序與定義的字節序不一致引發(fā)的異常。 11. System Call。執行sc指令產(chǎn)生此異常。 12. Decrementer。DEC寄存器產(chǎn)生的定時(shí)器異常,Linux PowerPC利用此異常實(shí)現時(shí)鐘中斷。 |
| E500內核使用IVPR和IVORn寄存器保存中斷向量。每個(gè)中斷向量的入口地址是IVPR+IVORn。IVPR提供中斷向量的基址,IVORn提供中斷向量的偏移。IVORn與異常的對應關(guān)系如下: IVOR0 Critical Interrupt IVOR1 Machine Check IVOR2 DSI IVOR3 ISI IVOR4 External Interrupt IVOR5 Alignment IVOR6 Program IVOR7 Unsupported IVOR8 System call IVOR9 Unsupported IVOR10 Decrementer IVOR11 Fixed-interval timer interrupt IVOR12 Watchdog timer interrupt IVOR13 Data TLB error IVOR14 Instruction TLB error IVOR15 Debug IVOR16 - IVOR31 Reserved IVOR32 SPE APU unavailable IVOR33 Embedded floating-point data exception IVOR34 Embedded floating-point round exception IVOR35 Performance monitor IVOR36 - IVOR63 Reserved E500這種處理異常的方式與MIPS大不一樣,MIPS是安排了幾個(gè)固定的入口,比如TLB refill入口就是0x80000000,而其他異常入口是0x80000180。然后通過(guò)軟件查看Cause(ExeCode)位判斷是什么種類(lèi)的異常,然后再跳轉過(guò)去。不過(guò)現在MIPS支持了VI和EIC模式中斷,外部中斷處理可以不通過(guò)0x80000180的固定入口了。 E500的這種處理方式也便于在多處理器上實(shí)現AMP應用,比如同時(shí)運行兩個(gè)操作系統,這兩個(gè)操作系統不可能共享一個(gè)異常處理程序,則可以通過(guò)IVPR區別開(kāi)來(lái)。MIPS也有類(lèi)似的考慮,引入了EBase寄存器來(lái)做為異常入口的基址寄存器,也是便于多處理器上的AMP應用。 在Linux內核中,通過(guò)宏SET_IVOR來(lái)設置IVORn寄存器,比如,對于外部中斷處理程序,則調用SET_IVOR(4, ExternalInput)。其中,“4”表示使用IVOR4寄存器,“ExternalInput”表示外部中斷處理程序的地址(低16位)。對于IVPR的初始化,則通過(guò)對IVPR直接賦值,即將interrupt_base的高地址賦給IVPR。 在Linux內核初始化的時(shí)候,會(huì )把所有需要初始化的IVOR賦上恰當的值。當有對應異常發(fā)生時(shí),直接跳轉到IVPR+IVORn所指向的地址即可。 |
| 在E500內核中,一個(gè)外部中斷的處理機制大致如下: 1. 捕捉到外部中斷信號#cint,#int 2. 保存被中斷程序的返回地址到SRR0寄存器中,這個(gè)寄存器類(lèi)似于MIPS的EPC寄存器 3. 保存MSR寄存器到SRR1中,如果是地址異常還會(huì )保存錯誤地址到DEAR寄存器中,類(lèi)似于MIPS中的BadVaddr寄存器 4. 保留MSR寄存器中的CE,DE,ME位,其余全部清除。因此,E500在處理外部中斷時(shí),還可以被Critical中斷,調試中斷和Machine Check中斷重入 5. 清除PR,IS,DS位。此時(shí),處理器運行在內核模式 6. 根據IVPR和IVOR4寄存器獲得中斷向量,進(jìn)行中斷程序執行 7. 中斷程序執行結束后,使用rfi指令返回。rfi指令從SRR1寄存器恢復MSR寄存器,從SRR0寄存器中獲得中斷的返回地址,注意這兩步其實(shí)是一個(gè)原子操作 |
| 最近做了一個(gè)磁盤(pán)性能分析的工作,環(huán)境是在一個(gè)4核的x86機器上,有一塊IDE的硬盤(pán),用兩個(gè)版本不同的kernel?,F象是,老版本kernel的性能比新版本的要高很多。測試的程序就是簡(jiǎn)單的dd命令。拿到之后,開(kāi)始分析,簡(jiǎn)單分析了一下磁盤(pán)訪(fǎng)問(wèn)數據zaikernel中所經(jīng)的路徑: page cache->block layer->IDE driver 在這段期間從page cache到disk的數據傳輸,可能出現中斷和DMA。 首先第一步是排除page cache的影響,先看了一下/proc/sys/vm目錄下的一些關(guān)于page cache的設置,兩個(gè)系統上是一樣的。然后用dd命令的iflag=direct參數,這樣dd命令可以繞過(guò)page cache,直接寫(xiě)磁盤(pán),就是kernel中的direct I/O。結果還是老版本的性能高很多。這樣,基本可以確定不是page cache引起的問(wèn)題。 其次,就是查看block layer和IDE driver的問(wèn)題。大概看了一下,沒(méi)有多大改變,性能上不能有很大的區別。所以,block layer和IDE driver也不是問(wèn)題所在。 最后,就看一下中斷和DMA的情況了。查看了一下/proc/interrupts文件,發(fā)現老版本上中斷只有幾千個(gè),而新版本上中斷卻又幾十萬(wàn)個(gè),差的也太多了??磥?lái)性能問(wèn)題就是太多的中斷造成的。既然page cache,block layer和IDE driver都已經(jīng)排除了,那么影響中斷數量的只有DMA一項了。于是,看了一下kernel的配置。果然,新版本中忘記配上IDEDMA了。打開(kāi)該選項后,兩個(gè)版本上性能基本差不多了。 |
| E500采用了兩級MMU機制,L1-MMU和L2-MMU,以及一些輔助寄存器和指令來(lái)實(shí)現虛實(shí)地址的轉換。E500與其他PowerPC處理器相比的一個(gè)最大不同就是,E500不能禁止虛實(shí)地址轉換,并且支持兩個(gè)地址空間,分別是地址空間0與地址空間1。其實(shí)這點(diǎn)有些類(lèi)似于MIPS,除了直接通過(guò)虛擬地址來(lái)區分以外,MIPS處理器也沒(méi)有機制禁止/啟用地址翻譯。 L1-MMU包含I-L1VSP,D-L1VSP,I-L1TLB4K和D-L1TLB4K。I-L1VSP和D-L1VSP含有4個(gè)條目,采用全相連結構。I-L1TLB4K和D-L1TLB4K含有64個(gè)條目,采用4路組相連結構。L2-MMU包含TLB0和TLB1。其中TLB0含有256個(gè)條目,采用2路組相連結構。TLB1含有16個(gè)條目,采用全相連結構。TLB0用來(lái)進(jìn)行頁(yè)式映射,TLB1用來(lái)處理段式映射。 在E500內核中將MMU分為兩級有一下兩個(gè)作用: L1-MMU的訪(fǎng)問(wèn)速度較快。這個(gè)原理類(lèi)似于Cache的原理。 L1-MMU采用哈佛結構,也就是程序地址空間與數據地址空間分離,可以提高地址轉換的效率。但是L2-MMU沒(méi)有采用這種結構。 |
| 最近比較忙,一直沒(méi)有更新PowerPC的學(xué)習筆記,今天補上一篇。 E500是一個(gè)32位的處理器,支持4GB的地址空間。在內部使用41位的臨時(shí)虛擬地址,組成如下: 40 39 32 31 0 AS PID EA AS:來(lái)自于MSR寄存器的IS或DS位。所以,E500可以根據AS位將地址空間分為兩種:地址空間0和地址空間1。但是,Linux并沒(méi)有使用這個(gè)功能。kernel和用戶(hù)空間的代碼,數據都在地址空間0中,即AS位一直是0。 PID:E500支持3個(gè)8位的PI的寄存器來(lái)保存進(jìn)程的PID。這點(diǎn)于MIPS的ASID作用一樣。但是,Linux并沒(méi)有使用PID,在TLB中簡(jiǎn)單的忽略PID的檢查,全部設為0。 EA:32位的有效地址。 下面介紹一下E500 MMU的結構。在E500中,MMU的entry包含下列字段: V:用來(lái)表示當前entry是否有效。為0時(shí)表示無(wú)效,為1時(shí)表示有效。在系統reset之后,所有entry的V位都設為0。 TS:就是上面地址空間中的AS。為0表示地址空間0,為1表示地址空間1。 TID[0:7]:就是上面地址空間中的PID。TID為0時(shí),忽略PID的比較。在Linux中,全為0。 EPN[0:19]:虛擬頁(yè)楨號。根據頁(yè)大小不同,有效的位數頁(yè)不同。 RPN[0:19]:物理頁(yè)楨號。 SIZE[0:3]:表示當前entry的頁(yè)大小。 PERMIS[0:5]:用于描述當前entry的訪(fǎng)問(wèn)控制位。分別是UR,SR,UW,SW,UX,SX。分別表示用戶(hù)態(tài)和內核態(tài)的讀/寫(xiě)/執行權限。 WIMGE[0:4]:W表示當前entry是write through還是write back。I表示當前entry是否忽略Cache。M表示對此數據區的訪(fǎng)問(wèn)需要進(jìn)行存儲一致性處理。G表示對相應存儲區域進(jìn)運行保護。E表示當前entry是小端還是大端。 X0,X1:描述一些額外屬性。 U[0:3]:自定義用途。 IPROT:當IPROT為1時(shí),表示當前entry被保護。不能使用tlbivax指令無(wú)效該entry。只能用tlbwe指令清除。在E500中只有TLB1支持該位,在TLB0中,該位一直為0。 |
| E500有一系列寄存器用于管理MMU。 PID0-2寄存器:用于保存當前進(jìn)程的PID,該寄存器只有54-63位有效。 MMUCSR0寄存器:用于使無(wú)效TLB0和TLB1的所有entry。該寄存器由兩位組成:L2TLB0_FI使無(wú)效TLB0的所有entry;L2TLB1_FI使無(wú)效TLB1的所有entry。 MMUCFG寄存器:用來(lái)保存當前MMU的配置信息,包括PID寄存器數量,大小,TLB的數量等。 TLB0CFG和TLB1CFG寄存器:用于描述TLB0和TLB1的配置信息,包括entry數量,頁(yè)表尺寸等信息。 除上述寄存器外,E500還包含一些MAS寄存器,主要作用就是維護MMU中TLB的entry,作用類(lèi)似于MIPS中的EntryHi和EntryLo寄存器。其中MAS1-3中存放的各個(gè)字段與TLB entry中的各個(gè)字段一一對應,MAS0寄存器用于決定寫(xiě)哪個(gè)TLB的哪個(gè)entry,作用類(lèi)似于MIPS中的random和index寄存器。 MAS0寄存器:TLBSEL字段用于選擇要操作的TLB,0表示TLB0,1表示TLB1。ESEL字段用于選擇TLB的entry。當使用TLB1時(shí),ESEL字段中低4位有效,用于選擇TLB1中的entry。當使用TLB0時(shí),ESEL中只有最低位有效,因為T(mén)LB0是兩路組相連。此時(shí),E500還需要MAS2寄存器的EPN的第45-51位決定組內不同的entry。NV位用于確定如何替換TLB0中的entry。 MAS1寄存器: 32 33 40 47 51 52 55 V IPROT TID TS SIZE MAS2寄存器: 32 51 57 58 59 60 61 62 63 EPN X0 X1 W I M G E MAS3寄存器: 32 51 54 57 58 59 60 61 62 63 RPN U0-U3 UX SX UW SW UR SR MAS4寄存器:用于存放當TLB miss異常發(fā)生時(shí),對MAS0-3寄存器自動(dòng)加載而使用的默認值,也就是說(shuō)MAS4寄存器的內容是硬件寫(xiě)入的。E500為了提高TLB miss異常的效率,在異常出現時(shí),E500會(huì )用MAS4寄存器中的值,自動(dòng)填寫(xiě)MAS0-2寄存器中的一部分內容: MAS0[TLBSEL] <- MAS4[TLBSELD] MAS1[TID] <- MAS4[TIDSELD] MAS1[TSIZE] <- MAS4[TSIZED] MAS2[X0,X1] <- MAS4[X0D,X1D] MAS2[WIMGE] <- MAS4[WD,ID,MD,GD,ED] MAS6寄存器:用于對TLB進(jìn)行檢索,MAS6寄存器提供SPID0和SAS,也就是PID和AS字段。 |
| 風(fēng)河將移植CGL Linux和WorkBench開(kāi)發(fā)環(huán)境,支持Sun UltraSPARC T2多核處理器。首先獲得支持的板子是Sun Netra CP3260 ATCA。該板子基于8核,64線(xiàn)程的UltraSPARC T2處理器。在2006年11月,風(fēng)河已經(jīng)完成了一個(gè)demo版的CGL Linux在UltraSPARC T1上。 UltraSPARC T2有8個(gè)核,核心頻率可以達到900MHz到1.4GHz,但是功耗低于95瓦,平均下來(lái)每個(gè)硬件線(xiàn)程低于2瓦。同時(shí)T2還將帶有10G以太網(wǎng),PCI-E等擴展I/O接口。還有浮點(diǎn)和加密處理單元等。 |
| 內核的一個(gè)基本原則就是:在中斷或者說(shuō)原子上下文中,內核不能訪(fǎng)問(wèn)用戶(hù)空間,而且內核是不能睡眠的。也就是說(shuō)在這種情況下,內核是不能調用有可能引起睡眠的任何函數。一般來(lái)講原子上下文指的是在中斷或軟中斷中,以及在持有自旋鎖的時(shí)候。內核提供了四個(gè)宏來(lái)判斷是否處于這幾種情況里: #define in_irq() (hardirq_count()) //在處理硬中斷中這四個(gè)宏所訪(fǎng)問(wèn)的count都是thread_info->preempt_count。這個(gè)變量其實(shí)是一個(gè)位掩碼。最低8位表示搶占計數,通常由spin_lock/spin_unlock修改,或程序員強制修改,同時(shí)表明內核容許的最大搶占深度是256。 8-15位表示軟中斷計數,通常由local_bh_disable/local_bh_enable修改,同時(shí)表明內核容許的最大軟中斷深度是256。 位16-27是硬中斷計數,通常由enter_irq/exit_irq修改,同時(shí)表明內核容許的最大硬中斷深度是4096。 第28位是PREEMPT_ACTIVE標志。用代碼表示就是: PREEMPT_MASK: 0x000000ff SOFTIRQ_MASK: 0x0000ff00 HARDIRQ_MASK: 0x0fff0000 凡是上面4個(gè)宏返回1得到地方都是原子上下文,是不容許內核訪(fǎng)問(wèn)用戶(hù)空間,不容許內核睡眠的,不容許調用任何可能引起睡眠的函數。而且代表thread_info->preempt_count不是0,這就告訴內核,在這里面搶占被禁用。 但是,對于in_atomic()來(lái)說(shuō),在啟用搶占的情況下,它工作的很好,可以告訴內核目前是否持有自旋鎖,是否禁用搶占等。但是,在沒(méi)有啟用搶占的情況下,spin_lock根本不修改preempt_count,所以即使內核調用了spin_lock,持有了自旋鎖,in_atomic()仍然會(huì )返回0,錯誤的告訴內核目前在非原子上下文中。所以凡是依賴(lài)in_atomic()來(lái)判斷是否在原子上下文的代碼,在禁搶占的情況下都是有問(wèn)題的。 |
聯(lián)系客服