本章介绍Hexagon处理器的寄存器。
通用寄存器 控制寄存器
通用寄存器用于所有通用计算,包括地址生成和标量及向量算术。
控制寄存器支持特殊用途的处理器功能,如硬件循环和谓词。
Hexagon处理器有32个32位通用寄存器(命名为R0至R31)。这些寄存器用于存储几乎所有指令中的操作数。
加载/存储指令的内存地址 算术/逻辑指令的数据操作数 矢量指令的矢量操作数
比如说
R1 = memh(R0)
R4 = add(R2,R3)
R28 = vaddh(R11,R10)
图2-1显示了一般的寄存器。
Aliased registers
三个通用寄存器–R29到R31–用于支持子程序(7.3.2节)和软件堆栈(8章)。这些寄存器被子程序和堆栈指令隐含地修改。它们有符号别名,用来指示这些寄存器何时被作为子程序和堆栈寄存器访问。
比如说:
SP = add(SP, #-8)
allocframe
call init
// SP is alias of R29
// Modifies SP (R29) and FP (R30)
// Modifies LR (R31)
Register pairs
一般的寄存器可以被指定为寄存器对,代表一个64位的寄存器。比如说:
R1:0 = memd(R3) // Load doubleword
R7:6 = valignb(R9:8,R7:6, #2) // Vector align
注意 寄存器对中的第一个寄存器必须始终是奇数,第二个必须是下一个低的寄存器。
Hexagon处理器包括一组32位控制寄存器,它们提供对处理器功能的访问,如程序计数器、硬件循环和矢量谓词。
与一般寄存器不同,控制寄存器只能在以下情况下作为指令操作数使用。
需要特定控制寄存器作为操作数的指令 寄存器转移指令
列如:
R2 = memw(R0++M1)
R9 = PC
LC1 = R3
// Auto-increment addressing mode (M1)
// Get program counter (PC)
// Set hardware loop count (LC1)
注意 当一个控制寄存器被用于寄存器的转移时,另一个操作数必须是一个普通 寄存器。
别名的寄存器
控制寄存器有数字别名(C0到C31)。表2-3列出了控制寄存器的别名。
C1:0 = R5:4 // C1:0 specifies the LC0/SA0 register pair
Register pairs
控制寄存器可以被指定为寄存器对,代表一个64位的寄存器。指定为对的控制寄存器必须使用它们的数字别名。例如。
注意 一个控制寄存器对中的第一个寄存器必须总是奇数,第二个必须是下一个低的 寄存器。
程序计数器(PC)寄存器指向要执行的下一个指令包(3.3节)。它被指令的执行隐性地修改,但可以直接读取。比如说。
R7 = PC // Get program counter
注意 PC寄存器是只读的:对它的写入没有效果。
Hexagon处理器包括两组循环寄存器以支持嵌套硬件循环(第7.2节)。每个硬件循环都由一对寄存器实现,其中包含循环计数和循环起始地址。循环寄存器由循环指令隐式修改,但也可以直接访问。比如说
loop0(start, R4) // 修改LC0和SA0 (LC0=R4, SA0=&start)
LC1 = R22 // 设置循环1计数
R9 = SA1 // 获得循环1的起始地址
用户状态寄存器(USR)存储用户程序可以访问的处理器状态和控制位。状态位包含某些指令的状态结果,而控制位包含用户可设置的处理器模式,用于硬件预取。比如说。
R9:8 = vaddw(R9:8, R3:2):sat // Vector add words
R6 = USR // Get saturation status
USR存储以下状态和控制值。
缓存预取启用(第5.10.6节)。
缓存预取状态(第5.10.6节)
浮点模式(第4.3.4节)
浮点状态(第4.3.4节)
硬件循环配置(第7.2节)
粘性饱和溢出(第4.2.2节)
注意 用户控制寄存器向USR的转移不能与浮点指令(第4.3.4节)组合在一个指令包中。
每当向USR的转移改变了Enable trap位[29:25],在新的异常编程生效之前,必须执行isync指令(第5.11节)。
修改器寄存器(M0-M1)用于以下寻址模式。
间接自动递增寄存器寻址 循环寻址
位反转寻址
间接自动递增
在间接自动递增寄存器寻址中(第5.8.9节),修改器寄存器存储了一个有符号的32位值,指定了增量(或减量)值。比如说
M1 = R0 // Set modifier register
R3 = memw(R2++M1) // Load word
循环
增量 有符号的自动增量值。
在循环寻址中(第5.8.10节),修改器寄存器存储循环缓冲区长度和相关的 "K "和 "I "值。比如说
M0 = R7 // Set modifier register
R0 = memb(R2++#4:circ(M0)) // Load from circ buffer pointed
// to by R2 with size/K vals in M0
R0 = memb(R7++I:circ(M1)) // Load from circ buffer pointed
// to by R7 with size/K/I vals in M1
在位反转寻址中(第5.8.12节),修改器寄存器存储一个有符号的32位值,指定增量(或减量)值。比如说:
M1 = R7 // Set modifier register
R2 = memub(R0++M1:brev) // The address is (R0.H | bitrev(R0.L))
// The orginal R0 (not reversed) is added
// to M1 and written back to R0
谓词寄存器(P0-P3)存储标量和向量比较指令的状态结果(第6章)。比如说:
P1 = cmp.eq(R2, R3)
if (P1) jump end
R8 = P1
P3:0 = R4
// Scalar compare
// Jump to address (conditional)
// Get compare status (P1 only)
// Set compare status (P0-P3)
四个谓词寄存器可以被指定为一个寄存器四元组(P3:0),代表一个32位的寄存器。
注意 与其他控制寄存器不同,谓词寄存器只有8位宽,因为矢量比较最多可返回8个状态结果。
循环起始寄存器(CS0 - CS1)在循环寻址中存储循环缓冲区的起始地址(5.8.10节)。比如说
CS0 = R5
M0 = R7
R0 = memb(R2++#4:circ(M0))
// Set circ start register
// Set modifier register
// Load from circ buffer pointed
// to by CS0 with size/K vals in M0
用户通用指针(UGP)寄存器是一个通用的控制寄存器。比如说:
R9 = UGP // Get UGP
UGP = R3 // Set UGP
全局指针(GP)用于GP-relative寻址。比如说:
GP = R7 // Set GP
R2 = memw(GP+#200) // GP-relative load
循环计数寄存器(UPCYCLELO - UPCYCLEHI)存储了一个64位的值,其中包含自Hexagon处理器上次复位以来执行的处理器循环数。比如说:
R5 = UPCYCLEHI
R4 = UPCYCLELO
R5:4 = UPCYCLE
// Get cycle count (high)
// Get cycle count (low)
// Get cycle count
注意 实时操作系统必须授予访问这些寄存器的权限。如果没有这个权限,从用户代码中读取这些寄存器总是返回0。
帧限制寄存器(FRAMELIMIT)存储了为软件堆栈保留的内存区域的低地址(8.3.1节)。比如说:
R9 = FRAMELIMIT // Get frame limit register
FRAMELIMIT = R3 // Set frame limit register
帧密钥寄存器(FRAMEKEY)存储的是密钥值,当返回地址存储在软件堆栈中时,它被用来进行XOR-窜改(8.3.2节)。比如说
R2 = FRAMEKEY // Get frame key register
FRAMEKEY = R1 // Set frame key register
数据包计数寄存器(PKTCOUNTLO - PKTCOUNTHI)存储了一个64位的值,包含了自上次写入PKTCOUNT寄存器后执行的指令包的当前数量。比如说:
R9 = PKTCOUNTHI
R8 = PKTCOUNTLO
R9:8 = PKTCOUNT
// Get packet count (high)
// Get packet count (low)
// Get packet count
数据包计数可以被配置为仅在特定的处理器模式下运行(例如,仅用户模式,或仅访客和监控模式)。每个模式的配置由用户状态寄存器中的位[12:10]控制(第2.2.3节)。
有例外的数据包不被计算为已提交的数据包。
注意 每个硬件线程都有自己的一组数据包计数寄存器。
实时操作系统必须授予访问这些寄存器的权限。没有这个权限,从用户代码中读取这些寄存器总是返回0。
当一个值被写入PKTCOUNT寄存器时,在该值被存储到寄存器之前,64位的数据包计数值被递增。
Qtimer寄存器(UTIMERLO - UTIMERHI)提供了对Qtimer全局参考数值的访问。它们使Hexagon软件能够读取64位时间值,而不需要执行昂贵的AHB加载。例如:
R5 = UTIMERHI
R4 = UTIMERLO
R5:4 = UTIMER
// Get Qtimer reference count (high)
// Get Qtimer reference count (low)
// Get Qtimer reference count
这些寄存器是只读的 - 它们由硬件自动更新,总是包含当前的Qtimer值。
注意 实时操作系统必须授予访问这些寄存器的权限。如果没有这个权限,从用户代码中读取这些寄存器总是返回0。