英飞凌 AURIX TC3XX内核寄存器结构及指令集详解

  作者:林Nova 时间:2025-04-01来源:英飞凌汽车电子生态圈

本文主要介绍Infineon AURIX™️2G TC3XX系列芯片内核结构及相关寄存器,并结合代码示例讲解芯片内核指令集系统。

#01前  言
1.1 内核
芯片内核芯片内核(Core)是中央处理器(CPU)中的独立处理单元,能够执行指令、处理数据和控制操作。
英飞凌AURIX™️2G TC3XX系列芯片的内核架构是一种混合架构,同时结合了精简指令集计算机(RISC)和复杂指令集计算机(CISC)的特征,称为TriCore™️内核架构(以下简称TriCore™️)。它是一款专门为实时性进行了优化的32位的多核同构嵌入式系统架构。之所以命名为TriCore™️,是因为其集成了RISC架构、DSP架构和实时系统的技术于一体,形成了兼具三方优势的内核架构。
图片
TriCore™ 架构采用了RISC的高性能load/store数据处理模式,同时具有DSP的数据处理能力。TriCore™ 是32位处理器架构,因此采用32位地址空间,支持可选的虚拟地址空间。
下面是TriCore™ 架构的特性:   


1.2 指令集系统
每款内核都有其匹配的内核指令集,内核架构也成为指令集架构,比如我们日常使用的计算机(Intel或AMD芯片),使用的就是X86指令集,内核就属于X86架构。常见的还有ARM架构、DSP架构和RISC-V架构。当我们想要掌握某款芯片,基于该芯片进行系统搭建时,就必须要了解该芯片的内核。
指令集系统是一种用于计算机或其他数字处理器的体系结构,它规定了处理器能够执行的指令集合,包括操作码、操作数和指令格式等。不同的处理器架构(如x86、ARM、MIPS等)都有自己的指令集系统,这些系统决定了处理器如何执行各种操作,从简单的加法和乘法到复杂的条件分支和内存访问。指令集系统的设计直接影响了处理器的性能、功耗和软件兼容性。   
嵌入式领域的芯片一般都是精简指令集内核,比如RISC-V、ARM等, 精简指令集(RISC,Reduced Instruction Set Computing)是一种计算机处理器架构设计理念,其核心思想是将处理器的指令集设计得相对较小和简单,以提高执行效率。相对于复杂指令集计算机(CISC)架构而言,RISC架构强调用更少、更基本的指令来完成操作,并且这些指令的执行时间相对较短。
和ARM指令集一样,TriCore™ 指令属于通用寄存器型结构中的寄存器-寄存器结构,即除了load和store以外,其余指令的操作数都来自通用寄存器组。
本文介绍的TriCore™ 内核是AURIX™️ TC3XX系列中使用的TriCoreTC1.6.2版本的内核架构。由于篇幅原因,无法讲解所有指令,但是通过本文的介绍,读者能够较好地掌握TriCore™ 指令系统的结构和使用,然后就可以自行利用内核手册进行查阅和学习。

#02内核介绍
接下来针对内核结构,首先介绍程序模型、通用寄存器和系统寄存器等。
2.1 程序模型(Programming Model)
该小节主要介绍内核的数据类型、数据格式、存储模式以及地址空间等内容,因为计算机的本质其实是对数据的处理和呈现,因此要理解其内核,首先要理解其数据的处理模型。
2.1.1 数据及内存
首先我们来看TriCore™ 的数据模型,注意,这里提到的数据模型,是指内核在处理数据时的视角,并非我们C语言中定义数据的视角。
TriCore™ 架构支持下面几种数据类型:


TriCore™ 是32位架构,因此大多数指令都是基于32位数据进行处理的,与数据类型相对应,其指令支持的数据格式如下图:
图片
程序对数据的读取、存储操作是有对齐要求的,见下表:   
图片
同样外设的地址访问也是有对齐要求的:
图片
TriCore™ 的数据存储采用小端模式,低字节存储在低地址。
图片
TriCore™ 是32位内核,因此地址最多支持0xFFFF FFFF,也就是4GB空间大小。因此地址空间的定义被分为16个段(Segments)[0 - F],地址最高位的4个Bit表示段号,每个段256MBytes大小。其中F段被用于外设寄存器地址段。
2.1.2 寻址模式    
我们知道,计算机在进行数据计算过程中,需要不断进行数据的读取和存储,这中间有一个重要的流程就是寻址。不同的内核支持不同的寻址模式,TriCore™ 支持的寻址模式如下表:
图片


2.2 通用寄存器和系统寄存器(General Purpose and System Registers)
TriCore™ 的内核寄存器包括通用寄存器和系统寄存器,系统寄存器包括程序状态寄存器等。其中系统寄存器的地址是16位内核地址,读写采用的是专用的指令,MTCR(Move To Core Register)和MFCR(Move From Core Register)。
2.2.1 通用寄存器
通用寄存器是计算机体系结构中的寄存器,其设计用途是存储通用数据,而不是特定的数据类型或用途。通用寄存器可以存储整数、浮点数、内存地址等各种数据类型,而不受限于特定的操作或指令。   
在许多计算机架构中,通用寄存器用于执行各种操作,如算术运算、逻辑运算、数据移动等。程序员可以使用这些寄存器来存储临时变量、中间计算结果和其他通用数据。通用寄存器的优点在于其灵活性和通用性,允许程序员更自由地使用寄存器来执行各种任务,而不受到特定数据类型或操作的限制。这有助于提高程序的灵活性和性能。
相比于ARM内核,TriCore™ 有两类通用寄存器,包括16个32位数据寄存器(D[0]~D[15])和16个32位地址寄存器(A[0]~A[15])。
图片
其按照功能有如下几类:


数据和地址寄存器的分离促进了算术和内存操作并行执行的高效实现。同时,相邻的两个奇偶寄存器还可以成对进行访问,比如通过E[0]访问由D[0]和D[1]组成的64位数据(D[1]存放高8位),通过P[0]访问由A[0]和A[1]组成的64位地址。   
众所周知,在操作系统调度或中断程序切换过程中,系统需要保存上下文,其中主要的内容是保存寄存器。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 程序状态信息寄存器(Program State Information Registers)
程序状态信息寄存器包含三个寄存器:程序计数器,也就是我们常说的PC指针;程序状态字PSW;前一个上下文信息PCXI。           图片
PC寄存器为32位程序计数器,反映了程序执行的位置,始终指向下一条即将执行的指令。
图片
图片    图片
程序状态字PSW顾名思义,是用来反映程序执行过程中的状态信息。其中:


图片



图片
前一个上下文信息PCXI用来进行程序的上下文加载,当程序需要返回时,或中断结束调用时,都需要从这个地方向前链接,因此PCXI也称为链接字(Link Word),它和CSA的配合使得TriCore™️能够实现一套高效的硬件上下文保存机制,下面我们会介绍,这里先看PCXI的内容:


TriCore™️的上下文机制是利用CSA建立链表,PCXI指示链表的首位,以此形成函数调用栈关系。
2.2.3 栈管理寄存器
栈管理包括用户栈和中断栈,用到前文提到的栈指针寄存器A[10]、中断指针寄存器ISP(Interrupt Stack Pointer),以及前文提到的PSW中的IS位,来进行栈的管理。当运行非中断程序时,CPU正常根据栈指针寄存器使用普通程序栈,当从Task进入中断时,硬件会自动切换到中断栈。
图片
栈指针寄存器通常是程序启动时进行初始化,根据链接脚本分配的栈空间,设置栈起始地址。   图片
中断栈指针寄存器的使用,能够防止中断程序侵占Task程序的栈。在程序进入中断PSW.IS==0时,系统会从ISP中加载中断栈地址到栈指针中,以使用中断的栈;如果是中断的嵌套,PSW.IS==1,则不进行任何操作,继续使用中断栈。当中断执行完毕后,PSW和栈指针都会从上下文中恢复,因此Task程序得以继续使用原先的栈。
2.2.4 系统控制寄存器
图片
系统控制寄存器SYSCON的主要功能是对所属核进行控制(该寄存器有外设32位地址,可进行跨核访问,比如主核通过控制从核的BHALT位设置启动),主要包括:


2.2.5 Core_ID寄存器
图片
Core_ID寄存器用来获取当前核的ID,在多核系统中,共用代码尤其是OS,获取所在核是非常重要的。
中断、内存保护、Trap相关的寄存器我们将会在模块单独介绍时候进行说明,这里就不展开介绍了。


#03TriCore™️指令集结构
TriCore™是一种通用的、32位的微控制器-DSP,针对实时嵌入式系统进行了优化的多核同构架构。
TriCore™️指令集支持32位指令和16位指令,支持嵌入式常用的微控制器系列处理指令,也支持一些DSP数据处理指令。   
3.1 指令语法
和ARM等指令集系统一样,TriCore™️指令集的语法也是由指令和操作数组成,操作数可以是立即数、寄存器或内存。一条指令包括基础操作符、操作修饰符、操作数修饰符和操作数组成。如下面这条指令,是将一个立即数写入地址寄存器的高位:
图片


3.1.1 基础操作符
基础操作符即该指令的操作定义,操作类型较多,下文会给出部分示例,此处就不一一列出了。
3.1.2 操作修饰符
TriCore™️指令集的操作修饰符见下表:   图片
图片
3.1.3 操作数修饰符
TriCore™️操作数修饰符见下表:
图片
有些16位指令还会使用隐式寄存器,即该条指令不指定寄存器,而是固定使用约定好的寄存器,隐式寄存器包含下面几种:   


3.2 程序状态字标志位(用户状态位)
之前的内核寄存器介绍中提到过,程序状态字寄存器PSW中有5个用户状态位,用于指令的状态存储。
图片
这5个状态位会会影响指令的操作逻辑,同时它们也会因为指令的操作结果而发生变化。比如第一个Carry位,它表示计算进位,比如在使用加法指令ADDC(带进位的加)中结果溢出了,那C位就会置位;并且如果在执行前C位已经置位了,那ADDC的结果就会加1。
在手册中每个指令后都会描述PSW的影响情况,可在指令详细信息中查看。   图片
3.3 指令权限
TriCore™️内核分为三个权限等级,因此有些指令对权限是有限制的。下表列出的指令表示只有该权限等级下能够使用。
图片
#04TriCore™ 指令介绍
本章节将分类介绍TriCore™ 指令集中的指令,同时包括部分操作修饰符和操作数修饰符的介绍。
4.1 如何查询指令手册
TriCore™ 指令数百条本文不一一解释,这里先介绍下如何查询TriCore™ 指令手册。
作为示例,我们来看ADD.A指令的文档介绍,这里各部分用序号标出,以做解释。   
图片

  1. 指令助记符;

  2. 指令长名;

  3. 32bit格式指令的描述;

  4. 16bit格式指令的描述;

  5. 32bit格式指令使用语法,有时候操作数可以有多种类型,所以会有多种指令语法描述;

  6. 操作码,也就是指令译码最后的二进制数格式;  

  7. 指令的运行逻辑描述,这里使用了仿C语言的RTL(Register Transfer Level)语言描述,在1.3章节中有语法介绍;

  8. 16bit格式指令语法;

  9. 16bit格式指令操作码;

  10. 16bit格式指令逻辑描述;

  11. 对PSW中状态位的影响,如溢出等;

  12. 32bit格式指令示例;

  13. 16bit格式指令示例;

  14. 其他相关指令。


当我们遇到要查询某条指令的时候,先根据其结构识别出它的指令助记符(并非所有指令-修饰符组合在内核手册中都有示例),然后查到对应的指令,再根据其逻辑及修饰符的逻辑解释其指令含义。
4.2 Load/Store指令
在Load-Store结构的内核中,Load(LD.X)和Store(ST.X)指令是唯一两条能够访问内存的指令,它们是内存和寄存器间的桥梁,其余的所有指令都是基于寄存器进行操作的。
Load/Store指令支持以下这些寻址模式:
图片
其中最主要的还是绝对地址寻址和基址-偏移寻址。
TriCore™ 指令集的Load/Store除了支持字节(byte)、半字(Half Word)、字(Word)、双字(Double Word)等基础数据类型,还支持浮点型和地址型(地址寄存器的读写)。TriCore™ 中一个字Word,代表32字节。   
图片
下面对Load/Store指令结合操作修饰符和操作数修饰符进行指令说明,这里需要注意的是,TriCore™ 的通用寄存器是分为通用地址寄存器通用数据寄存器两类的,因此操作数修饰符会强调操作数类型。

Assembly language                  

LD.A    A0, [A15]       //将A15指向的内存中的4字节数据,取到A0中,A表示操作数为地址寄存器

LD.BU   D5, [A0]        //将A0指向的内存中的一字节无符号数据,取到D5中,B表示Byte,1字节,U表示无符号                  
LD.D    E0, [A0]        //将A0指向的内存中的8字节数据,取到E0中(D0+D1),D表示Double Word                  
LD.H    D1, [A0]        //将A0指向的内存中的2字节数据,取到D1的低16位中,H表示Half Word                  
LD.W    D2, [A2]0x44    //将A2+0x44指向的内存中的4字节数据,取到D2中,W表示Word,0x44表示地址偏移                  
ST.A    [A1], A0        //将A0的数据,存储到A1指向的4字节内存中,A表示操作数为地址寄存器                  
ST.B    [A1], D0        //将D0的1字节数据,存储到A1指向的1字节内存中,B表示长度为1字节                  
ST.D    [A1], E0        //将E0(D0+D1)中的8字节数据,存储到A1指向的8字节内
存中,D表示Double Word                  
ST.H    [A0], D0        //将D0中的2字节数据,存储到A0指向的2字节内存中,H表示Half Word                  
ST.W    [A1], D0        //将D0中的4字节数据,存储到A1指向的4字节内存中,W表示Word      
  


4.3 算术运算指令
算术运算指令包括MOVE、加减乘除、绝对值、逻辑运算、移位等,还包括计算非零bit位等。
TriCore™ 算术运算符有一种Saturation运算,操作修饰符为S,即饱和运算,意思是说当运算结果超出内存大小,结果是当前内存的最大值。比如uint8的最大值为255,用ADDS去计算200+200,得到的结果是255。同样的如果减法运算值小于负的最大值,结果也是负的最大值。
4.3.1 MOV指令
MOV指令是将一个立即数或者寄存器的值,赋值给另一个寄存器的指令。

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指令
加法和减法指令类似,此处只列出加法的说明。
加法指令是ADD,普通加法运算中,溢出会自动去除高位,比如uint8的255+100,结果等于99。   
而带修饰符的加法运算,是会修改PSW的用户状态位的,比如ADDC指令如果溢出会修改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    //计算无符号D1+D2的值,如果溢出则做饱和运算处理,结果存放到D3中


4.3.3 MUL乘法指令
乘法指令为MUL,部分乘法指令同样也会修改PSW的用户状态位。

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    //计算无符号D1*D2的值,结果存放到E0(D1+D2)中


4.3.4 DIV除法指令
TriCore™ 指令集支持32位的有/无符号除法,硬件不支持双精度64位触发,对于双精度64位的除法,则需要依赖于编译器的软件实现。另外由于除法指令计算时间相对较长,会消耗数个指令周期,因此会降低中断的实时性响应,这种影响与商的有效位成正比。除法运算在计算时结果可以占据一个寄存器对,商保存在第一个寄存器中,余数保存在第二个寄存器中。
有符号整数除法的计算相对于加法等有较多的判断逻辑:   

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 - r
emainder)/divisor                  
    }                  
    E[c][31:0] = quotient;                  
    E[c][63:32] = remainder;


无符号整数的计算也类似上面的形式:

C                  
DIV.U   E[c], D[a], D[b]       //计算无符号D[a]/D[b],商存放到E[c][31:0],余数存放到E[c][63:32]中,U表示无符号                  
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; 


浮点数的除法运算逻辑整体不复杂,根据IEEE754规范计算32位浮点数除法,指令的后台执行流程相对要多一些,这里不详细列出,感兴趣的读者可以查看内核手册。

Assembly language                  

DIV.F    D3, D1, D2    //计算浮点数D1/D2的值,结果存放到D3中       


4.3.5 ABS/ABSDIF绝对值指令
TriCore™ 指令集支持直接进行有符号数的绝对值运算,或者计算两个数的差值的绝对值。

Assembly language                  
ABS       D1, D2        //计算D2的绝对值,结果存放到D1中                  
ABSDIF    D3, D1, D2    //计算D1-D2的值的绝对值,结果存放到D3中


4.3.6 MIN/MAX比较指令
TriCore™ 指令集支持直接对两个数进行比较,取其较大值或较小值,输入源可以是整形或者无符号整形。

Assembly language                  

MIN        D3, D1, D2       //比较D1和D2的大小,将较小的存放到D3中             
MIN.U      D3, D1, 8        //比较D1和8的大小,将较小的存放到D3中,U表示无符号数                  

MAX        D3, D1, D2       //比较D1和D2的大小,将较大的存放到D3中            
MAX.U      D3, D1, 8        //比较D1和8的大小,将较大的存放到D3中,U表示无符号数


4.3.7 CADD/CSUB/SEL条件指令
TriCore™ 对于整数运算提供了条件执行指令,即先对某个数进行判断,来决定是否执行加减或者选择赋值来源。

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               
SELN        D4, D1, D2, 8     //如果D1为零,则D4=D2,否则D4=8


4.3.8 AND/OR/XOR逻辑指令
TriCore™ 支持AND/OR/XOR等按位的逻辑指令,同时也支持结果取反的NAND/NOR/XNOR指令,以及源操作数取反的ANDN、ORN等。后两者容易混淆,要注意辨别,比如NAND和ANDN。   

Assembly language                  
AND        D3, D1, D2        //计算D1与D2的按位与,结果存放到D3中,即D3 = D1&D2                  
OR         D3, D1, 0xCC      //计算D1与0xCC的按位或,结果存放到D3中,即D3 = D1|0xCC                  
XOR        D3, D1, D2        //计算D1与D2的按位异或,结果存放到D3中,即D3 = D1^D2                  
NAND       D3, D1, D2        //计算D1与D2的按位与,并按位取反,结果存放到D3中,即D3 = ~(D1&D2)                  
ANDN       D3, D1, D2        //计算D2的按位取反,然后与D1按位取与,结果存放到D3中,即D3 = D1&~D2                  
NOT        D1                //计算D1的按位取反,结果存放到D1中,即D1 = ~D1


4.3.9 CLO/CLZ/CLS计位指令
TriCore™ 提供了用于位计数的功能,能够计算高位连续的0位、1位或符号位。
CLO(Count Leading Ones)用于计算从最高位开始一共多少个连续的1,比如0xF000 0000计算的结果为4,0xF800 0000计算的结果为5。
CLZ(Count Leading Zeros),用于计算从最高位开始一共多少个连续的0,比如0x0FFF 0000计算的结果为4,0x07FF 0000计算的结果为5。
CLS(Count Leading Signs),用于计算从次高位开始一共多少个与最高位相同值的连续位数,比如第31位为1,则从30开始计算连续的1的个数。

Assembly language                  
CLO        D2, D1        //计算D1的CLO的值,结果存放到D2中                  
CLZ        D2, D1        //计算D1的CLZ的值,结果存放到D2中                  
CLS        D2, D1        //计算D1的CLS的值,结果存放到D2中


4.3.10 SH/SHA/SHAS移位指令
TriCore™ 的移位指令支持有符号数移位,如果是正数就左移,如果是负数就右移。

Assembly language                  
SH    D3, D1, D2    //按照D2的值对D1进行移位,填充值始终为0,结果存放到D3中                  
SHA   D3, D1, D2    //按照D2的值对D1进行移位,左移填充位为0,右移填充位同符号位,结果存放到D3中                  
SHAS  D3, D1, D2    //与SHA计算相同,区别在于结果取饱和操作,S代表SATURATION        


4.3.11 EXTR/INSERT位提取/插入指令
TriCore™ 支持对数据进行位提取和位插入功能。
位提取是指提取源操作数的某个bit段,赋值给目的操作数,操作数可以是整形或无符号整形。

Assembly language                  
EXTR        D3, D1, D2, #4      //D2[4:0]为pos,4为width,然后按照下图从D1中截取,赋值到D3中


图片

Assembly language                  
EXTR.U        D3, D1, D2, #4      //D2[4:0]为pos,4为width,然后按照下图从D1中截取,赋值到D3中,U表示无符号


图片

Assembly language                  
DEXTR        D3, D1, D2, 5    //将{D1,D2}左移5位,然后截取[63:32]位,赋值给D3


图片

Assembly language                  
INSERT D3, D1, D2, D4, #8    //D4[4:0]为Pos,8为width,将D2按照下图位置左移,然后覆盖到D1该段,结果赋值给D3


图片
4.4 Packed打包计算
TriCore™ 的算术运算符还有一种打包运算方法,对于一个32位数据,可以按照字节或者半字分别计算,结果分别存放到指定位置。
图片图片

Assembly language                  
ADD.B    D3, D1, D2    //将D1与D2按照字节依次相加,结果分字节存放到D3中,任意一个字节计算溢出,V和SV都会置位                  
ADD.H    D3, D1, D2    //将D1与D2按照半字依次相加,结果分半字存放到D3中,任意一个半字计算溢出,V和SV都会置位


4.5 EQ/NE/LE/GE比较指令
TriCore™ 中比较指令的使用也是比较频繁的,主要用于条件指令的操作修饰符,比如分支跳转等。


另外对于大于和小于等于,TriCore™ 是没有指令的,需要依赖上述指令隐式实现。
图片

Assembly language                  

LT    D3, D1, D2    //D3 = (D1 <D2)                  

GE    D3, D1, D2    //D3 = (D1>=D2)               


4.6 地址指令    TriCore™ 中对于地址的运算和操作和数据还是具有一定差异的,同时硬件上采用了通用地址寄存器等设计来实现加速。一般使用赋值加载以及LEA指令进行地址计算。
LEA(Load Effective Address)指令用于计算绝对地址,并保存到指定的地址寄存器中。

Assembly language                  
MOVH.A    A5, #0x7001        //将0x7001赋值给A5高16位,低16位置0             
LEA       A5, [A5]0x4864     //将A5中的值加上0x4864,然后赋值给A5,组成0x7001 4864地址值


4.7 跳转指令
TriCore™ 中的分支指令大致分为以下三种:

Assembly language                  
J    foobar            //跳转到foobar                  
JI   A5                //跳转到A5指向地址                  

JL   foobar         //将下一条指令地址写入到返回地址寄存器中,并跳转到foobar   CALL foobar       //保存高上下文,将下一条指令地址写入到返回地址寄存器中,跳转到foobar                  
JEQ  D1, D2, foobar    //如果D1==D2,跳转到foobar                  
JGE  D1, D2, foobar    //如果D1>=D2,跳转到foobar


4.8 上下文相关指令
TriCore™ 的上下文除了中断、Trap以及CALL、RET指令能够操作以外,还提供了专有的上下文操作指令。主要分为以下两类:


这里要注意区分,第二种使用方法虽然也能够保存和加载通用寄存器,但是它是不使用CSA区域的,同时也不会更改PCX和FCX寄存器。
4.9 系统相关指令
TriCore™ 提供了内核系统指令,主要包括System Call、指令和程序屏障、开关中断等功能。
4.9.1 SYSCAL系统调用指令
TriCore™ 的系统调用是通过Trap6来实现的,一般用来给OS做内核模式切换使用的。

Assembly language                  
SYSCALL    4    //执行System Call,4为系统调用的入参


4.9.2 DYSNC/ISYNC数据/指令屏障
这两条指令的作用是作为数据/指令屏障而使用的。
DYSNC指令
在计算机科学中,数据屏障(Memory Barrier)是一种用于控制处理器和内存之间数据同步的机制。它确保在多核或多线程系统中的内存访问顺序得到正确的维护,避免了由于并发访问导致的数据不一致性和竞态条件。DYSNC作为一个屏障,将其前后的指令进行分隔,保证后面的指令一定在前面的所有内存访问完成后执行,包括Cache,防止因编译器优化或指令流水、多线程等导致的数据访问次序错误。
ISYNC指令
指令屏障(Instruction Barrier)是另一种用于控制处理器执行指令顺序的机制。它确保在处理器执行指令时,按照程序员的预期顺序执行,避免指令重排或者乱序执行导致的问题。另外如果指令修改了系统的状态,比如内存保护设置,则该指令能够保证其后执行的所有程序都是按照新的内存保护设置执行的。

Assembly language                  
DYSNC    //数据屏障                  
ISYNC     //指令屏障
        


4.9.3 MFCR/MTCR核特殊功能寄存器指令
TriCore™ 的核特殊功能寄存器CSFR是每个核特有的,而且对于多核其地址是不进行区分的,因此必须通过特殊的指令进行操作,哪个核执行该指令就作用于哪个核。
MFCR(Move From Core Special Function Register)读取指令
MFCR指令用于从CSFR中读取内容,比如我们最常用的读取当前核的ID。
MTCR(Move To Core Special Function Register)操作指令
MTCR指令用于修改CSFR中的内容,后面必须跟一条ISYNC用于指令屏障,保证操作完成。

Assembly language                  
MFCR    D15, #0xFE1C    //读取CoreID,结果保存到D15中                  
MTCR    #0xFE04, D15    //修改PSW寄存器,将其值修改为D15


4.9.4 ENABLE/DISABLE开关中断
TriCore™ 中每个核的中断使能是相互独立的,只需要使用ENABLE/DISABLE指令即可。

Assembly language                  
ENABLE    //开中断                  
DISABLE   //关中断


4.9.5 TRAP指令
TriCore™ 提供了用户软件触发Trap的方法,可以使用TRAPV或TRAPSV,当OverFlow或StickyOverflow位置位时触发Trap。 

Assembly language                  
TRAPV     //Trap on overflow                  
TRAPSV   //Trap on sticky overflow


4.10 16Bit指令
TriCore™ 的大部分指令在某些情况下是支持16位格式的,甚至有些指令只有16位格式,具体可以参考内核手册,上面有每条指令的格式说明。   


#05使用示例
下面我们通过一段示例代码,通过对汇编进行说明,来帮助读者了解TriCore™ 的指令集。下面的代码通过辗转相除法求两个数的最大公约数,数据源和结果都用了全局变量,以使用Load/Store指令。
5.1 示例代码

C                  
//变量声明                  
volatile int MyResult;                  

volatile int num1=15, num2=20;    //volatile防止编译器优化                 
                    
// 函数声明                  
int TestInstruction(void);                  
int gcd(int a, int b);                  
                    
void echoInit(void){                  
    Test
Instruction();                  
}                  
                    
int TestInstruction(void) {                  
    // 计算并输出最大公约数                  
    MyResult = gcd(num1, num2);                  
    printf("GCD of %d and %d is %dn", num1, num2, MyResult);                  
    return 0;                  
}                  
                    
// 计算最大公约数的函数                  
int gcd(int a, int b) {                  
    int temp;                  
    // 辗转相除法                  
    while (b != 0) {                  
        temp = b;                  
 
       b = a % b;                  
        a = temp;                  
    }                  
    return a;                  
}


5.2 TestInstruction调用   
我们首先看TestInstruction的调用这里,使用的是Jump指令,而不是JL或者Call。
图片
这样做的好处是,当该条代码是调用方的最后一条指令,在其执行完毕之后已经没有必要返回调用方了,而是直接返回调用方的上一层调用方,这样的优化能够节省系统时间,提高性能。
图片
但是缺点是调用栈中就会少一层,图中echoInit就没有显示,不便于调试。所以我们在调试过程中经常会遇到调用栈的信息缺失,或者使用Return调试操作的时候会直接返回两层的情况,都是这个原因。
5.3 TestInstruction函数
TestInstruction函数的C语言一共只有三行,我们一一展开描述。
图片
第一行是以num1和num2为入参,计算最大公约数:


第二行是调用printf函数将其显示出来:


图片


最后一行是return 0:


5.4 gcd函数
gcd函数这里是while循环,通过条件跳转,来进行循环计算。   
图片


至此全部的函数调用就介绍完了,不同的编译器或者编译优化等级、编译选项等可能有不同的汇编结果,但是整体的内容是差不多的,希望读者能够通过这个示例,了解TriCore™ 指令集的框架结构。


#06小  结
本文介绍了英飞凌的AURIX™️ TC3XX内核TriCore™ 的内核架构,并对其指令集系统进行了讲解,并通过代码示例进行讲解,通过本文读者能够对TriCore™ 内核及指令集有一定的了解和掌握。   


关键词: 英飞凌 AURIX TC3XX 内核寄存器

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版