英飛凌 AURIX TC3XX內核寄存器結構及指令集詳解
本文主要介紹Infineon AURIX??2G TC3XX系列芯片內核結構及相關(guān)寄存器,并結合代碼示例講解芯片內核指令集系統。
#01前 言
1.1 內核
芯片內核芯片內核(Core)是中央處理器(CPU)中的獨立處理單元,能夠執行指令、處理數據和控制操作。
英飛凌AURIX??2G TC3XX系列芯片的內核架構是一種混合架構,同時(shí)結合了精簡(jiǎn)指令集計算機(RISC)和復雜指令集計算機(CISC)的特征,稱(chēng)為TriCore??內核架構(以下簡(jiǎn)稱(chēng)TriCore??)。它是一款專(zhuān)門(mén)為實(shí)時(shí)性進(jìn)行了優(yōu)化的32位的多核同構嵌入式系統架構。之所以命名為TriCore??,是因為其集成了RISC架構、DSP架構和實(shí)時(shí)系統的技術(shù)于一體,形成了兼具三方優(yōu)勢的內核架構。
TriCore? 架構采用了RISC的高性能load/store數據處理模式,同時(shí)具有DSP的數據處理能力。TriCore? 是32位處理器架構,因此采用32位地址空間,支持可選的虛擬地址空間。
下面是TriCore? 架構的特性:
32位架構
4GB的地址空間
同時(shí)支持16位和32位指令,減少代碼大小
大多數指令在一個(gè)周期內執行
分支指令(使用分支預測)
使用并行數據存儲器,實(shí)現低中斷延遲與快速自動(dòng)上下文切換
專(zhuān)用接口特定于應用程序的協(xié)處理器,以允許添加定制指令
零開(kāi)銷(xiāo)回路功能
雙/單時(shí)鐘周期,16x16位乘法累加單元(可選飽和)
可選浮點(diǎn)單元(FPU)和內存管理單元(MMU)
廣泛的位處理能力
單指令多數據(SIMD)打包數據操作(2x16位或4x 8位操作數)
靈活的中斷優(yōu)先級方案
字節和位尋址
數據內存和CPU寄存器的小端字節排序
內存保護
調試支持
1.2 指令集系統
每款內核都有其匹配的內核指令集,內核架構也成為指令集架構,比如我們日常使用的計算機(Intel或AMD芯片),使用的就是X86指令集,內核就屬于X86架構。常見(jiàn)的還有ARM架構、DSP架構和RISC-V架構。當我們想要掌握某款芯片,基于該芯片進(jìn)行系統搭建時(shí),就必須要了解該芯片的內核。
指令集系統是一種用于計算機或其他數字處理器的體系結構,它規定了處理器能夠執行的指令集合,包括操作碼、操作數和指令格式等。不同的處理器架構(如x86、ARM、MIPS等)都有自己的指令集系統,這些系統決定了處理器如何執行各種操作,從簡(jiǎn)單的加法和乘法到復雜的條件分支和內存訪(fǎng)問(wèn)。指令集系統的設計直接影響了處理器的性能、功耗和軟件兼容性。
嵌入式領(lǐng)域的芯片一般都是精簡(jiǎn)指令集內核,比如RISC-V、ARM等, 精簡(jiǎn)指令集(RISC,Reduced Instruction Set Computing)是一種計算機處理器架構設計理念,其核心思想是將處理器的指令集設計得相對較小和簡(jiǎn)單,以提高執行效率。相對于復雜指令集計算機(CISC)架構而言,RISC架構強調用更少、更基本的指令來(lái)完成操作,并且這些指令的執行時(shí)間相對較短。
和ARM指令集一樣,TriCore? 指令集屬于通用寄存器型結構中的寄存器-寄存器結構,即除了load和store以外,其余指令的操作數都來(lái)自通用寄存器組。
本文介紹的TriCore? 內核是AURIX?? TC3XX系列中使用的TriCore?TC1.6.2版本的內核架構。由于篇幅原因,無(wú)法講解所有指令,但是通過(guò)本文的介紹,讀者能夠較好地掌握TriCore? 指令系統的結構和使用,然后就可以自行利用內核手冊進(jìn)行查閱和學(xué)習。
#02內核介紹
接下來(lái)針對內核結構,首先介紹程序模型、通用寄存器和系統寄存器等。
2.1 程序模型(Programming Model)
該小節主要介紹內核的數據類(lèi)型、數據格式、存儲模式以及地址空間等內容,因為計算機的本質(zhì)其實(shí)是對數據的處理和呈現,因此要理解其內核,首先要理解其數據的處理模型。
2.1.1 數據及內存
首先我們來(lái)看TriCore? 的數據模型,注意,這里提到的數據模型,是指內核在處理數據時(shí)的視角,并非我們C語(yǔ)言中定義數據的視角。
TriCore? 架構支持下面幾種數據類(lèi)型:
Boolean:布爾型,FALSE表示0,TRUE表示1
Bit String:布爾串,一段Bit段,用于移位操作
Byte:字節,一個(gè)字節是8Bit的數據
Signed Fraction:有符號的分數,TriCore? 支持16位、32位、64位的分數
Address:地址表示一段32位地址數據(TriCore? 有專(zhuān)門(mén)的地址寄存器,下文會(huì )介紹)
Signed and Unsigned Integers:又符合和無(wú)符號整型,表示32位有、無(wú)符號數據
IEEE-754 Single-Precision Floating-Point Number:浮點(diǎn)數
TriCore? 是32位架構,因此大多數指令都是基于32位數據進(jìn)行處理的,與數據類(lèi)型相對應,其指令支持的數據格式如下圖:
程序對數據的讀取、存儲操作是有對齊要求的,見(jiàn)下表:
同樣外設的地址訪(fǎng)問(wèn)也是有對齊要求的:
TriCore? 的數據存儲采用小端模式,低字節存儲在低地址。
TriCore? 是32位內核,因此地址最多支持0xFFFF FFFF,也就是4GB空間大小。因此地址空間的定義被分為16個(gè)段(Segments)[0 - F],地址最高位的4個(gè)Bit表示段號,每個(gè)段256MBytes大小。其中F段被用于外設寄存器地址段。
2.1.2 尋址模式
我們知道,計算機在進(jìn)行數據計算過(guò)程中,需要不斷進(jìn)行數據的讀取和存儲,這中間有一個(gè)重要的流程就是尋址。不同的內核支持不同的尋址模式,TriCore? 支持的尋址模式如下表:
Absolute:絕對地址尋址模式,用于外設和全局變量的尋址
Base+Offset:基地址加偏移尋址方式,一般用于結構體成員尋址和局部變量的棧尋址
Pre-Increment and Pre-Decrement Addressing:預加/預減尋址,一般用于棧的操作
Post-Increment and Post-Decrement Addressing:后加/后減尋址,一般用于數據數據的處理指令
Circular:循環(huán)尋址,一般用于循環(huán)操作中
Bit-reverse:位翻轉尋址,用于FFT算法中
2.2 通用寄存器和系統寄存器(General Purpose and System Registers)
TriCore? 的內核寄存器包括通用寄存器和系統寄存器,系統寄存器包括程序狀態(tài)寄存器等。其中系統寄存器的地址是16位內核地址,讀寫(xiě)采用的是專(zhuān)用的指令,MTCR(Move To Core Register)和MFCR(Move From Core Register)。
2.2.1 通用寄存器
通用寄存器是計算機體系結構中的寄存器,其設計用途是存儲通用數據,而不是特定的數據類(lèi)型或用途。通用寄存器可以存儲整數、浮點(diǎn)數、內存地址等各種數據類(lèi)型,而不受限于特定的操作或指令。
在許多計算機架構中,通用寄存器用于執行各種操作,如算術(shù)運算、邏輯運算、數據移動(dòng)等。程序員可以使用這些寄存器來(lái)存儲臨時(shí)變量、中間計算結果和其他通用數據。通用寄存器的優(yōu)點(diǎn)在于其靈活性和通用性,允許程序員更自由地使用寄存器來(lái)執行各種任務(wù),而不受到特定數據類(lèi)型或操作的限制。這有助于提高程序的靈活性和性能。
相比于A(yíng)RM內核,TriCore? 有兩類(lèi)通用寄存器,包括16個(gè)32位數據寄存器(D[0]~D[15])和16個(gè)32位地址寄存器(A[0]~A[15])。
其按照功能有如下幾類(lèi):
通用寄存器:D[0]~D[14]、A[2]~A[7]、A[12]~A[14]為真正意義上的通用寄存器
A[15]和D[15]為隱式寄存器(一般16位指令使用,指令語(yǔ)法中不用明確指出,默認使用該寄存器),32位指令下與通用寄存器功能相同,16位指令下作為默認的寄存器使用
A[0]、A[1]、A[8]、A[9]為全局寄存器,在函數調用、中斷、異常等場(chǎng)景都不會(huì )進(jìn)行操作
A[10]為棧指針寄存器
A[11]為返回地址寄存器
數據和地址寄存器的分離促進(jìn)了算術(shù)和內存操作并行執行的高效實(shí)現。同時(shí),相鄰的兩個(gè)奇偶寄存器還可以成對進(jìn)行訪(fǎng)問(wèn),比如通過(guò)E[0]訪(fǎng)問(wèn)由D[0]和D[1]組成的64位數據(D[1]存放高8位),通過(guò)P[0]訪(fǎng)問(wèn)由A[0]和A[1]組成的64位地址。
眾所周知,在操作系統調度或中斷程序切換過(guò)程中,系統需要保存上下文,其中主要的內容是保存寄存器。TriCore? 的通用寄存器分為高上下文和低上下文,高上下文包括A[10]~A[15]、D[8]~D[15],低上下文包括A[2]~A[7]、D[0]~D[7]以及A[11],其中僅有返回地址寄存器A[11]在兩部分中都存在。A[0]、A[1]、A[8]、A[9]作為全局地址寄存器,不存儲在上下文中。
2.2.2 程序狀態(tài)信息寄存器(Program State Information Registers)
程序狀態(tài)信息寄存器包含三個(gè)寄存器:程序計數器,也就是我們常說(shuō)的PC指針;程序狀態(tài)字PSW;前一個(gè)上下文信息PCXI。
PC寄存器為32位程序計數器,反映了程序執行的位置,始終指向下一條即將執行的指令。
程序狀態(tài)字PSW顧名思義,是用來(lái)反映程序執行過(guò)程中的狀態(tài)信息。其中:
USB:用戶(hù)狀態(tài)位(User Status Bits),用來(lái)保存指令執行過(guò)程中的狀態(tài)標志位,如溢出信息等,用于后續指令作條件判斷
RES:預留
PRS[2](Bit15)& PRS[1:0](Bit12,Bit13):保護寄存器集切換位(Protection Register Set bit),內存保護寄存器有多套配置,PRS用來(lái)選擇程序保護寄存器或數據保護寄存器的配置切換
S:安全任務(wù)標識符(Safety Task Identifier),標注當前任務(wù)是否為安全任務(wù)
IO:I/O訪(fǎng)問(wèn)權限級別控制位(Access Privilege Level Control),TriCore? 內核對于外設寄存器的訪(fǎng)問(wèn)是由權限級別的:
0:User-0 Mode,無(wú)權訪(fǎng)問(wèn)外設,在此權限下訪(fǎng)問(wèn)會(huì )產(chǎn)生PSE和MPP異常,也無(wú)法進(jìn)行開(kāi)關(guān)中斷
1:User-1 Mode,常規訪(fǎng)問(wèn)權限,在此權限下能夠訪(fǎng)問(wèn)大部分外設,包括Port口的讀寫(xiě)、定時(shí)器的讀取和大部分I/O狀態(tài)讀取,能夠開(kāi)關(guān)中斷
2:Supervisor Mode,具有完全的外設訪(fǎng)問(wèn)控制權限
3:Reserved Value
IS:中斷??刂莆?/span>(Interrupt Stack Control),TriCore??內核是有獨立的中斷棧寄存器ISP的,當進(jìn)入中斷且IS位為0的時(shí)候,硬件會(huì )先將棧寄存器置為ISP的值,以使用中斷的特有棧(當然,在此之前硬件會(huì )自動(dòng)保存SP指針,中斷返回后會(huì )自動(dòng)加載回來(lái),不用擔心被覆蓋),并將IS位置1 。因為是共享棧,如果發(fā)生中斷嵌套,則不作任何操作,繼續往下使用中斷棧
GW:全局地址寄存器寫(xiě)權限位,決定是否可寫(xiě)入全局地址寄存器,1表示有權限;全局地址寄存器一般用來(lái)指向某個(gè)關(guān)鍵的地址區域或關(guān)鍵的數據結構體,比如OS的任務(wù)調度控制塊等;另外通常A[0]被用于短數據的讀取和寫(xiě)入,A[1]也一般為編譯器操作預留,A[8]和A[9]未作為編譯器預留,一般用于指向系統的關(guān)鍵數據
CDE:調用深度計數使能位(Call Depth Count Enable),TriCore??內核是有調用深度檢查的,每次調用計數器加1,最大6位計數器,也就是最多支持64層調用(每個(gè)Task或者中斷具有獨立的上下文,因此獨立計數),當超過(guò)調用上限,會(huì )產(chǎn)生異常;將CDE置0,可暫時(shí)關(guān)閉調用計數,但是在下次Call指令執行時(shí)會(huì )自動(dòng)再次打開(kāi)
CDC:調用深度計數器(Call Depth Counter),調用深度計數器,7個(gè)Bit位寬,溢出時(shí)產(chǎn)生異常,也可修改CDC降低調用深度上限,比如改為1111100,則4次調度就會(huì )產(chǎn)生異常
前一個(gè)上下文信息PCXI用來(lái)進(jìn)行程序的上下文加載,當程序需要返回時(shí),或中斷結束調用時(shí),都需要從這個(gè)地方向前鏈接,因此PCXI也稱(chēng)為鏈接字(Link Word),它和CSA的配合使得TriCore??能夠實(shí)現一套高效的硬件上下文保存機制,下面我們會(huì )介紹,這里先看PCXI的內容:
RES:預留
PCPN:前一個(gè)CPU中斷優(yōu)先級(Previous CPU Priority Number),在之前關(guān)于中斷的文章中我們提到過(guò),中斷的處理流程的一個(gè)步驟,是將ICR.CCPN,也就是當前的CPU中斷優(yōu)先級位,寫(xiě)入到PCPN,也就是本寄存器位中,用于中斷環(huán)境的保存,中斷執行完之后再進(jìn)行恢復
PIE:先前中斷使能位(Previous Interrupt Enable),同PCPN,在中斷處理流程中將CPU中斷使能狀態(tài)位ICR.IE,保存到PIE中,用于中斷環(huán)境保存,中斷執行完之后再進(jìn)行恢復
UL:高、低上下文標簽(Upper or Lower Context Tag),1表示高上下文,0表示低上下文
PCXS,PCXO:CSA是存儲在內存中的,PCXS和PCXO用于指示存儲地址,物理地址有32位,但是實(shí)際的內存空間沒(méi)有這么大的,且CSA是64字節對齊,地址末尾6個(gè)為0,所以只需要20位就能指示上下文存儲位置,具體算法是Addr=(PCXS<<12)|(PCXO<<6)
TriCore??的上下文機制是利用CSA建立鏈表,PCXI指示鏈表的首位,以此形成函數調用棧關(guān)系。
2.2.3 棧管理寄存器
棧管理包括用戶(hù)棧和中斷棧,用到前文提到的棧指針寄存器A[10]、中斷指針寄存器ISP(Interrupt Stack Pointer),以及前文提到的PSW中的IS位,來(lái)進(jìn)行棧的管理。當運行非中斷程序時(shí),CPU正常根據棧指針寄存器使用普通程序棧,當從Task進(jìn)入中斷時(shí),硬件會(huì )自動(dòng)切換到中斷棧。
棧指針寄存器通常是程序啟動(dòng)時(shí)進(jìn)行初始化,根據鏈接腳本分配的??臻g,設置棧起始地址。
中斷棧指針寄存器的使用,能夠防止中斷程序侵占Task程序的棧。在程序進(jìn)入中斷且PSW.IS==0時(shí),系統會(huì )從ISP中加載中斷棧地址到棧指針中,以使用中斷的棧;如果是中斷的嵌套,PSW.IS==1,則不進(jìn)行任何操作,繼續使用中斷棧。當中斷執行完畢后,PSW和棧指針都會(huì )從上下文中恢復,因此Task程序得以繼續使用原先的棧。
2.2.4 系統控制寄存器
系統控制寄存器SYSCON的主要功能是對所屬核進(jìn)行控制(該寄存器有外設32位地址,可進(jìn)行跨核訪(fǎng)問(wèn),比如主核通過(guò)控制從核的BHALT位設置啟動(dòng)),主要包括:
RES:預留
BHALT:啟動(dòng)凍結狀態(tài)控制位(Boot halt status and release),當芯片啟動(dòng)后,除了主核以外,該位都會(huì )置1,代表該核處于凍結狀態(tài),主核通過(guò)對該位寫(xiě)0來(lái)啟動(dòng)該核,啟動(dòng)后寫(xiě)1無(wú)效
U1_IO:User-1 Peripheral access as supervisor,前面我們提到用戶(hù)模式包括User-0、User-1和Supervisor三種模式,該位能夠允許User-1獲得對外設的全部訪(fǎng)問(wèn),不改變模式的情況下提高權限
U1_IED:User-1 Instruction execution disable,禁止或使能User-1模式下開(kāi)關(guān)中斷
ESDIS:Emulator Space Disable,仿真地址禁用
TS:進(jìn)入異常(Trap)后PSW.S的默認值
IS:進(jìn)入中斷后PSW.S的默認值
TPROTEN:Temporal Protection Enable,1表示使能,0表示關(guān)閉
PROTEN:內存保護使能,注意需要先設置好內存保護配置再使能
FCDSF:空閑上下文列表耗盡粘滯標志位(Free Context List Depleted Sticky Flag),該位表征是否發(fā)生過(guò)上下文列表耗盡,因為CSA的空間是RAM中設置的,如果任務(wù)或中斷過(guò)多,且都調用過(guò)深會(huì )導致CSA耗盡,從而該位置位,知道清除
2.2.5 Core_ID寄存器
Core_ID寄存器用來(lái)獲取當前核的ID,在多核系統中,共用代碼尤其是OS,獲取所在核是非常重要的。
中斷、內存保護、Trap相關(guān)的寄存器我們將會(huì )在模塊單獨介紹時(shí)候進(jìn)行說(shuō)明,這里就不展開(kāi)介紹了。
#03TriCore??指令集結構
TriCore?是一種通用的、32位的微控制器-DSP,針對實(shí)時(shí)嵌入式系統進(jìn)行了優(yōu)化的多核同構架構。
TriCore??指令集支持32位指令和16位指令,支持嵌入式常用的微控制器系列處理指令,也支持一些DSP數據處理指令。
3.1 指令語(yǔ)法
和ARM等指令集系統一樣,TriCore??指令集的語(yǔ)法也是由指令和操作數組成,操作數可以是立即數、寄存器或內存。一條指令包括基礎操作符、操作修飾符、操作數修飾符和操作數組成。如下面這條指令,是將一個(gè)立即數寫(xiě)入地址寄存器的高位:
基礎操作符:定義了該指令的基礎操作,比如mov就是賦值,add就是累加;
操作修飾符:定義該操作更準確的細節,比如movh中的h定義操作a15的高16位;
操作數修飾符:定義了操作數的數據類(lèi)型,比如movh.a中的a定義了目標寄存器為地址寄存器;
操作數:需要操作的寄存器、立即數或內存。
3.1.1 基礎操作符
基礎操作符即該指令的操作定義,操作類(lèi)型較多,下文會(huì )給出部分示例,此處就不一一列出了。
3.1.2 操作修飾符
TriCore??指令集的操作修飾符見(jiàn)下表:
3.1.3 操作數修飾符
TriCore??的操作數修飾符見(jiàn)下表:
有些16位指令還會(huì )使用隱式寄存器,即該條指令不指定寄存器,而是固定使用約定好的寄存器,隱式寄存器包含下面幾種:
D[15]:通用數據寄存器D[15]可以作為16位指令的隱式數據寄存器使用;
A[15]:通用地址寄存器A[15]可以作為16位指令的隱式地址寄存器使用;
A[10]:A[10]為棧指針寄存器,所以對于棧相關(guān)操作指令默認操作數為A[10];
A[11]:A[11]為返回地址寄存器,即鏈接寄存器,所以跳轉指令默認使用A[11]作為指令默認的操作數。
3.2 程序狀態(tài)字標志位(用戶(hù)狀態(tài)位)
之前的內核寄存器介紹中提到過(guò),程序狀態(tài)字寄存器PSW中有5個(gè)用戶(hù)狀態(tài)位,用于指令的狀態(tài)存儲。
這5個(gè)狀態(tài)位會(huì )會(huì )影響指令的操作邏輯,同時(shí)它們也會(huì )因為指令的操作結果而發(fā)生變化。比如第一個(gè)Carry位,它表示計算進(jìn)位,比如在使用加法指令ADDC(帶進(jìn)位的加)中結果溢出了,那C位就會(huì )置位;并且如果在執行前C位已經(jīng)置位了,那ADDC的結果就會(huì )加1。
在手冊中每個(gè)指令后都會(huì )描述PSW的影響情況,可在指令詳細信息中查看。
3.3 指令權限
TriCore??內核分為三個(gè)權限等級,因此有些指令對權限是有限制的。下表列出的指令表示只有該權限等級下能夠使用。
#04TriCore? 指令介紹
本章節將分類(lèi)介紹TriCore? 指令集中的指令,同時(shí)包括部分操作修飾符和操作數修飾符的介紹。
4.1 如何查詢(xún)指令手冊
TriCore? 指令數百條本文不一一解釋?zhuān)@里先介紹下如何查詢(xún)TriCore? 指令手冊。
作為示例,我們來(lái)看ADD.A指令的文檔介紹,這里各部分用序號標出,以做解釋。
指令助記符;
指令長(cháng)名;
32bit格式指令的描述;
16bit格式指令的描述;
32bit格式指令使用語(yǔ)法,有時(shí)候操作數可以有多種類(lèi)型,所以會(huì )有多種指令語(yǔ)法描述;
操作碼,也就是指令譯碼最后的二進(jìn)制數格式;
指令的運行邏輯描述,這里使用了仿C語(yǔ)言的RTL(Register Transfer Level)語(yǔ)言描述,在1.3章節中有語(yǔ)法介紹;
16bit格式指令語(yǔ)法;
16bit格式指令操作碼;
16bit格式指令邏輯描述;
對PSW中狀態(tài)位的影響,如溢出等;
32bit格式指令示例;
16bit格式指令示例;
其他相關(guān)指令。
當我們遇到要查詢(xún)某條指令的時(shí)候,先根據其結構識別出它的指令助記符(并非所有指令-修飾符組合在內核手冊中都有示例),然后查到對應的指令,再根據其邏輯及修飾符的邏輯解釋其指令含義。
4.2 Load/Store指令
在Load-Store結構的內核中,Load(LD.X)和Store(ST.X)指令是唯一兩條能夠訪(fǎng)問(wèn)內存的指令,它們是內存和寄存器間的橋梁,其余的所有指令都是基于寄存器進(jìn)行操作的。
Load/Store指令支持以下這些尋址模式:
其中最主要的還是絕對地址尋址和基址-偏移尋址。
TriCore? 指令集的Load/Store除了支持字節(byte)、半字(Half Word)、字(Word)、雙字(Double Word)等基礎數據類(lèi)型,還支持浮點(diǎn)型和地址型(地址寄存器的讀寫(xiě))。TriCore? 中一個(gè)字Word,代表32字節。
下面對Load/Store指令結合操作修飾符和操作數修飾符進(jìn)行指令說(shuō)明,這里需要注意的是,TriCore? 的通用寄存器是分為通用地址寄存器和通用數據寄存器兩類(lèi)的,因此操作數修飾符會(huì )強調操作數類(lèi)型。
Assembly language LD.A A0, [A15] //將A15指向的內存中的4字節數據,取到A0中,A表示操作數為地址寄存器 LD.BU D5, [A0] //將A0指向的內存中的一字節無(wú)符號數據,取到D5中,B表示Byte,1字節,U表示無(wú)符號 |
4.3 算術(shù)運算指令
算術(shù)運算指令包括MOVE、加減乘除、絕對值、邏輯運算、移位等,還包括計算非零bit位等。
TriCore? 算術(shù)運算符有一種Saturation運算,操作修飾符為S,即飽和運算,意思是說(shuō)當運算結果超出內存大小,結果是當前內存的最大值。比如uint8的最大值為255,用ADDS去計算200+200,得到的結果是255。同樣的如果減法運算值小于負的最大值,結果也是負的最大值。
4.3.1 MOV指令
MOV指令是將一個(gè)立即數或者寄存器的值,賦值給另一個(gè)寄存器的指令。
Assembly language MOV D0, D1 //將D1中的值賦值給D0MOV.A A0, D0 //將D0中的值賦值給地址寄存器A0,A表示目的操作數是地址寄存器MOV.D D3, A4 //將地址寄存器A4的值賦值給數據寄存器D3,D表示目的操作數是數據寄存器MOV.AA A3, A4 //將地址寄存器A4的值賦值給地址寄存器A3,AA表示源操作數和目的操作數都是地址寄存器 MOVH D3, 180 //將立即數180賦值給D3的高16位,并將D3的低16位清零,H表示高位 |
4.3.2 ADD/SUB指令
加法和減法指令類(lèi)似,此處只列出加法的說(shuō)明。
加法指令是ADD,普通加法運算中,溢出會(huì )自動(dòng)去除高位,比如uint8的255+100,結果等于99。
而帶修飾符的加法運算,是會(huì )修改PSW的用戶(hù)狀態(tài)位的,比如ADDC指令如果溢出會(huì )修改Carry位。
Assembly language ADD D0, D1, D2 //計算D1+D2的值,結果存到D0中,溢出位舍棄,如255+1=0(uint8) ADD.A A0, A1, A2 //計算地址寄存器A1+A2的值,結果存到A0中,A表示操作數為地址寄存器 ADDX D3, D1, D2 //計算D1+D2的值,結果存到D3中,如果溢出,PSW.C=1,否則PSW.C=0 ADDC D3, D1, D2 //計算D1+D2+PSW.C的值,結果存到D3中,如果溢出,PSW.C=1,否則PSW.C=0 ADDI D3, D1, 858 //計算D1+858的值,結果存到D3中 ADDIH D3, D1, 0x8 //立即數移位加法,計算D1+0x8<<16的值,結果存到D3中,IH表示立即數左移16位 ADDS D3, D1, D2 //計算D1+D2的值,如果溢出則做飽和運算處理,結果存放到D3中 ADDS.U D3, D1, D2 //計算無(wú)符號D1+D2的值,如果溢出則做飽和運算處理,結果存放到D3中 |
4.3.3 MUL乘法指令
乘法指令為MUL,部分乘法指令同樣也會(huì )修改PSW的用戶(hù)狀態(tài)位。
Assembly language MUL D3, D1, D2 //計算D1*D2的值,溢出位舍棄,結果存放到D3中 MUL E0, D1, D2 //計算D1*D2的值,結果存放到E0(D1+D2)中 MULS D2, D1, D2 //計算D1*D2的值,溢出則做飽和運算處理,結果存放到D3中 MUL.U E0, D1, D2 //計算無(wú)符號D1*D2的值,結果存放到E0(D1+D2)中 |
4.3.4 DIV除法指令
TriCore? 指令集支持32位的有/無(wú)符號除法,硬件不支持雙精度64位觸發(fā),對于雙精度64位的除法,則需要依賴(lài)于編譯器的軟件實(shí)現。另外由于除法指令計算時(shí)間相對較長(cháng),會(huì )消耗數個(gè)指令周期,因此會(huì )降低中斷的實(shí)時(shí)性響應,這種影響與商的有效位成正比。除法運算在計算時(shí)結果可以占據一個(gè)寄存器對,商保存在第一個(gè)寄存器中,余數保存在第二個(gè)寄存器中。
有符號整數除法的計算相對于加法等有較多的判斷邏輯:
C DIV E[c], D[a], D[b] //計算D[a]/D[b],商存放到E[c][31:0],余數存放到E[c][63:32]中 dividend = D[a]; divisor = D[b]; if (divisor == 0) then { if (dividend >= 0) then { quotient = 0x7fffffff; remainder = 0x00000000; } else { quotient = 0x80000000; remainder = 0x00000000; } } else if ((divisor == 0xffffffff) AND (dividend == 0x80000000)) then { quotient = 0x7fffffff; remainder = 0x00000000; } else { remainder = dividend % divisor quotient = (dividend - remainder)/divisor } E[c][31:0] = quotient; E[c][63:32] = remainder; |
無(wú)符號整數的計算也類(lèi)似上面的形式:
C DIV.U E[c], D[a], D[b] //計算無(wú)符號D[a]/D[b],商存放到E[c][31:0],余數存放到E[c][63:32]中,U表示無(wú)符號 dividend = D[a]; divisor = D[b]; if (divisor == 0) then { quotient = 0xffffffff; remainder = 0x00000000; } else { remainder = dividend % divisor quotient = (dividend - remainder)/divisor } E[c][31:0] = quotient; E[c][63:32] = remainder; |
浮點(diǎn)數的除法運算邏輯整體不復雜,根據IEEE754規范計算32位浮點(diǎn)數除法,指令的后臺執行流程相對要多一些,這里不詳細列出,感興趣的讀者可以查看內核手冊。
Assembly language DIV.F D3, D1, D2 //計算浮點(diǎn)數D1/D2的值,結果存放到D3中 |
4.3.5 ABS/ABSDIF絕對值指令
TriCore? 指令集支持直接進(jìn)行有符號數的絕對值運算,或者計算兩個(gè)數的差值的絕對值。
Assembly language |
4.3.6 MIN/MAX比較指令
TriCore? 指令集支持直接對兩個(gè)數進(jìn)行比較,取其較大值或較小值,輸入源可以是整形或者無(wú)符號整形。
Assembly language MIN D3, D1, D2 //比較D1和D2的大小,將較小的存放到D3中 MAX D3, D1, D2 //比較D1和D2的大小,將較大的存放到D3中 |
4.3.7 CADD/CSUB/SEL條件指令
TriCore? 對于整數運算提供了條件執行指令,即先對某個(gè)數進(jìn)行判斷,來(lái)決定是否執行加減或者選擇賦值來(lái)源。
Assembly language CADD D4, D1, D2, D3 //如果D1非零,則D4=D2+D3,否則D4=D2 CADDN D4, D1, D2, 8 //如果D1為零,則D4=D2+8,否則D4=D2 CSUB D4, D1, D2, D3 //如果D1非零,則D4=D2-D3,否則D4=D2 SEL D4, D1, D2, D3 //如果D1非零,則D4=D2,否則D4=D3 |
4.3.8 AND/OR/XOR邏輯指令
TriCore? 支持AND/OR/XOR等按位的邏輯指令,同時(shí)也支持結果取反的NAND/NOR/XNOR指令,以及源操作數取反的ANDN、ORN等。后兩者容易混淆,要注意辨別,比如NAND和ANDN。
Assembly language |
4.3.9 CLO/CLZ/CLS計位指令
TriCore? 提供了用于位計數的功能,能夠計算高位連續的0位、1位或符號位。
CLO(Count Leading Ones)用于計算從最高位開(kāi)始一共多少個(gè)連續的1,比如0xF000 0000計算的結果為4,0xF800 0000計算的結果為5。
CLZ(Count Leading Zeros),用于計算從最高位開(kāi)始一共多少個(gè)連續的0,比如0x0FFF 0000計算的結果為4,0x07FF 0000計算的結果為5。
CLS(Count Leading Signs),用于計算從次高位開(kāi)始一共多少個(gè)與最高位相同值的連續位數,比如第31位為1,則從30開(kāi)始計算連續的1的個(gè)數。
Assembly language |
4.3.10 SH/SHA/SHAS移位指令
TriCore? 的移位指令支持有符號數移位,如果是正數就左移,如果是負數就右移。
Assembly language |
4.3.11 EXTR/INSERT位提取/插入指令
TriCore? 支持對數據進(jìn)行位提取和位插入功能。
位提取是指提取源操作數的某個(gè)bit段,賦值給目的操作數,操作數可以是整形或無(wú)符號整形。
Assembly language |
Assembly language |
Assembly language |
Assembly language |
4.4 Packed打包計算
TriCore? 的算術(shù)運算符還有一種打包運算方法,對于一個(gè)32位數據,可以按照字節或者半字分別計算,結果分別存放到指定位置。
Assembly language |
4.5 EQ/NE/LE/GE比較指令
TriCore? 中比較指令的使用也是比較頻繁的,主要用于條件指令的操作修飾符,比如分支跳轉等。
EQ (Equal)
NE (Not Equal)
LT (Less Than)
GE (Greater than or Equal to)
另外對于大于和小于等于,TriCore? 是沒(méi)有指令的,需要依賴(lài)上述指令隱式實(shí)現。
Assembly language LT D3, D1, D2 //D3 = (D1 <D2) GE D3, D1, D2 //D3 = (D1>=D2) |
4.6 地址指令 TriCore? 中對于地址的運算和操作和數據還是具有一定差異的,同時(shí)硬件上采用了通用地址寄存器等設計來(lái)實(shí)現加速。一般使用賦值加載以及LEA指令進(jìn)行地址計算。
LEA(Load Effective Address)指令用于計算絕對地址,并保存到指定的地址寄存器中。
Assembly language |
4.7 跳轉指令
TriCore? 中的分支指令大致分為以下三種:
Jump:跳轉指令,該指令不做任何其他操作,僅修改PC指針到指定地址運行,一般用于常規指令運算或分支跳轉;
Jump And Link:鏈接跳轉指令,該指令除了跳轉以外,還會(huì )將其下一條指令的地址存到返回地址寄存器中;
Call And Return:調用和返回指令,該指令必須成對使用,調用指令會(huì )保存高上下文,返回指令則會(huì )恢復高上下文。一般用于函數調用。
Assembly language JL foobar //將下一條指令地址寫(xiě)入到返回地址寄存器中,并跳轉到foobar CALL foobar //保存高上下文,將下一條指令地址寫(xiě)入到返回地址寄存器中,跳轉到foobar |
4.8 上下文相關(guān)指令
TriCore? 的上下文除了中斷、Trap以及CALL、RET指令能夠操作以外,還提供了專(zhuān)有的上下文操作指令。主要分為以下兩類(lèi):
SVLCX/RSLCX:低上下文保存和恢復指令,使用的內存是CSA區域,并同時(shí)會(huì )更新PCX以及FCX寄存器;
STUCX/STLCX/LDUCX/LDLCX:上下文加載和存儲指令,使用的區域需要指令指定,且不會(huì )更新PCX和FCX;
這里要注意區分,第二種使用方法雖然也能夠保存和加載通用寄存器,但是它是不使用CSA區域的,同時(shí)也不會(huì )更改PCX和FCX寄存器。
4.9 系統相關(guān)指令
TriCore? 提供了內核系統指令,主要包括System Call、指令和程序屏障、開(kāi)關(guān)中斷等功能。
4.9.1 SYSCAL系統調用指令
TriCore? 的系統調用是通過(guò)Trap6來(lái)實(shí)現的,一般用來(lái)給OS做內核模式切換使用的。
Assembly language |
4.9.2 DYSNC/ISYNC數據/指令屏障
這兩條指令的作用是作為數據/指令屏障而使用的。
DYSNC指令
在計算機科學(xué)中,數據屏障(Memory Barrier)是一種用于控制處理器和內存之間數據同步的機制。它確保在多核或多線(xiàn)程系統中的內存訪(fǎng)問(wèn)順序得到正確的維護,避免了由于并發(fā)訪(fǎng)問(wèn)導致的數據不一致性和競態(tài)條件。DYSNC作為一個(gè)屏障,將其前后的指令進(jìn)行分隔,保證后面的指令一定在前面的所有內存訪(fǎng)問(wèn)完成后執行,包括Cache,防止因編譯器優(yōu)化或指令流水、多線(xiàn)程等導致的數據訪(fǎng)問(wèn)次序錯誤。
ISYNC指令
指令屏障(Instruction Barrier)是另一種用于控制處理器執行指令順序的機制。它確保在處理器執行指令時(shí),按照程序員的預期順序執行,避免指令重排或者亂序執行導致的問(wèn)題。另外如果指令修改了系統的狀態(tài),比如內存保護設置,則該指令能夠保證其后執行的所有程序都是按照新的內存保護設置執行的。
Assembly language |
4.9.3 MFCR/MTCR核特殊功能寄存器指令
TriCore? 的核特殊功能寄存器CSFR是每個(gè)核特有的,而且對于多核其地址是不進(jìn)行區分的,因此必須通過(guò)特殊的指令進(jìn)行操作,哪個(gè)核執行該指令就作用于哪個(gè)核。
MFCR(Move From Core Special Function Register)讀取指令
MFCR指令用于從CSFR中讀取內容,比如我們最常用的讀取當前核的ID。
MTCR(Move To Core Special Function Register)操作指令
MTCR指令用于修改CSFR中的內容,后面必須跟一條ISYNC用于指令屏障,保證操作完成。
Assembly language |
4.9.4 ENABLE/DISABLE開(kāi)關(guān)中斷
TriCore? 中每個(gè)核的中斷使能是相互獨立的,只需要使用ENABLE/DISABLE指令即可。
Assembly language |
4.9.5 TRAP指令
TriCore? 提供了用戶(hù)軟件觸發(fā)Trap的方法,可以使用TRAPV或TRAPSV,當OverFlow或StickyOverflow位置位時(shí)觸發(fā)Trap。
Assembly language |
4.10 16Bit指令
TriCore? 的大部分指令在某些情況下是支持16位格式的,甚至有些指令只有16位格式,具體可以參考內核手冊,上面有每條指令的格式說(shuō)明。
#05使用示例
下面我們通過(guò)一段示例代碼,通過(guò)對匯編進(jìn)行說(shuō)明,來(lái)幫助讀者了解TriCore? 的指令集。下面的代碼通過(guò)輾轉相除法求兩個(gè)數的最大公約數,數據源和結果都用了全局變量,以使用Load/Store指令。
5.1 示例代碼
C volatile int num1=15, num2=20; //volatile防止編譯器優(yōu)化 |
5.2 TestInstruction調用
我們首先看TestInstruction的調用這里,使用的是Jump指令,而不是JL或者Call。
這樣做的好處是,當該條代碼是調用方的最后一條指令,在其執行完畢之后已經(jīng)沒(méi)有必要返回調用方了,而是直接返回調用方的上一層調用方,這樣的優(yōu)化能夠節省系統時(shí)間,提高性能。
但是缺點(diǎn)是調用棧中就會(huì )少一層,圖中echoInit就沒(méi)有顯示,不便于調試。所以我們在調試過(guò)程中經(jīng)常會(huì )遇到調用棧的信息缺失,或者使用Return調試操作的時(shí)候會(huì )直接返回兩層的情況,都是這個(gè)原因。
5.3 TestInstruction函數
TestInstruction函數的C語(yǔ)言一共只有三行,我們一一展開(kāi)描述。
第一行是以num1和num2為入參,計算最大公約數:
首先是兩條LD.W指令,因為是全局變量,所以要從內存中取出來(lái);
然后是CALL指令,調用gcd函數,TriCore? 的入參是依次使用D4~D7數據寄存器,或A4~A7地址寄存器;
然后返回值在D2寄存器中,使用ST.W將其存入MyResult全局變量中;
第二行是調用printf函數將其顯示出來(lái):
首先是三條LD.W指令將全局變量讀出來(lái)(這里因為我使用了volatile,所以沒(méi)有編譯器優(yōu)化,每次都重新讀寫(xiě));
然后是三條ST.W指令將加載的三個(gè)變量壓入棧中,作為printf函數的第2、3、4個(gè)入參;
然后是MOVH.A和LEA指令將地址0x8001 421C寫(xiě)入到A4寄存器中作為第一個(gè)入參,這里printf的第一個(gè)入參是字符串,傳入的是字符串的首地址,我們打開(kāi)內存使用ASCII格式可以看到這段字符;
然后進(jìn)行printf函數調用。
最后一行是return 0:
使用MOV指令,將返回值寫(xiě)入到D2寄存器中;
使用RET指令返回,前面提到,TestInstruction是通過(guò)Jump調用的,所以這里會(huì )直接返回到調用echoInit的那層;
5.4 gcd函數
gcd函數這里是while循環(huán),通過(guò)條件跳轉,來(lái)進(jìn)行循環(huán)計算。
首先是一條JG指令(目前觀(guān)察其功能同J,但無(wú)論是Infineon手冊還是Tasking手冊都沒(méi)有找到JG的相關(guān)描述),作為入口跳轉到0x80004078;
在0x80004078處通過(guò)條件指令JNE,當D5(形參b)不等于0時(shí)跳轉0x80004070進(jìn)入循環(huán);
然后在0x800040700開(kāi)始,執行MOV、DIV、MOV進(jìn)行算法的數學(xué)計算,隨后進(jìn)入下一輪的循環(huán)判斷;
當循環(huán)結束后執行到0x8000407C,這里將D4(形參a)的值寫(xiě)入到D2中,并調用RET函數返回;
至此全部的函數調用就介紹完了,不同的編譯器或者編譯優(yōu)化等級、編譯選項等可能有不同的匯編結果,但是整體的內容是差不多的,希望讀者能夠通過(guò)這個(gè)示例,了解TriCore? 指令集的框架結構。
#06小 結
本文介紹了英飛凌的AURIX?? TC3XX內核TriCore? 的內核架構,并對其指令集系統進(jìn)行了講解,并通過(guò)代碼示例進(jìn)行講解,通過(guò)本文讀者能夠對TriCore? 內核及指令集有一定的了解和掌握。
評論