高通公司HexagonTM处理器是一种通用的数字信号处理器,旨在为各种多媒体和调制解调器应用提供高性能和低能耗。V65是第六代Hexagon处理器架构中的一员。
■存储器
程序代码和数据存储在一个统一的32位地址空间。加载/存储架构支持一套完整的寻址模式,用于编译器代码生成和DSP应用编程。
■寄存器
32个32位通用寄存器可以作为单个寄存器或作为64位寄存器对被访问。通用寄存器保存所有的数据,包括标量、指针和打包的矢量数据。
■数据类型
指令可以对定点或浮点数据进行各种各样的操作。定点操作支持各种大小的标量和向量数据。浮点操作支持单精度数据。
■并行执行
指令可以被分组为超长指令字(VLIW)包,用于并行执行,每个包包含1到4条指令。矢量指令在单指令多数据(SIMD)矢量上操作。
■程序流程
支持可嵌套的零开销硬件循环。条件性/非条件性跳转和子程序调用同时支持PC-relative和寄存器间接寻址。两个程序流指令可以组合成一个数据包。
■ 指令流水线
管线危险由硬件解决:指令调度不受管线限制。
受管线限制的制约。
■代码压缩
复合指令将某些常见的操作序列(加-累加、移-加等)合并为一条指令。双工编码在一个32位字中表达两条并行指令。
■缓存内存
内存访问可以是缓存的,也可以是未缓存的。独立的L1指令和数据缓存存在于程序代码和数据中。一个统一的L2高速缓存可以部分或全部配置为紧耦合内存(TCM)。
■虚拟内存
内存是虚拟寻址的,虚拟到物理内存的映射由一个常驻操作系统处理。虚拟内存支持以一种与硬件无关的方式实现内存管理和内存保护。
图1-1显示了Hexagon V65处理器架构的主要功能单元。
内存和寄存器
指令排序器
执行单元
加载/存储单元
将原子变量减一。
Figure 1-1 Hexagon V65 processor architecture
Hexagon处理器具有一个统一的字节可寻址存储器。该存储器有一个单一的32位虚拟地址空间,可容纳指令和数据。它以小-endian模式运行。
Hexagon处理器有两组寄存器:通用寄存器和控制寄存器。
通用寄存器包括32个32位寄存器(命名为R0至R31),可以作为单个寄存器或作为对齐的64位寄存器对进行访问。通用寄存器用于包含所有的指针、标量、向量和累加器数据。
控制寄存器包括特殊用途的寄存器,如程序计数器、状态寄存器、循环寄存器等。
指令排序器在每个周期内处理1至4条指令的数据包。如果一个数据包包含一条以上的指令,这些指令将被并行执行。
一个数据包中允许的指令组合被限制在四个执行单元中可以并行执行的指令类型(如图1-1所示)。
双执行单元是相同的:每个单元包括一个64位移位器和一个带有四个16x16乘法器的向量乘/累加单元,以支持标量和向量指令。
这些单元还执行32位和64位ALU指令,以及跳转和循环指令。注意 每个执行单元都支持浮点指令。
双执行单元是相同的:每个单元包括一个64位移位器和一个带有四个16x16乘法器的向量乘/累加单元,以支持标量和向量指令。
这些单元还执行32位和64位ALU指令,以及跳转和循环指令。注意 每个执行单元都支持浮点指令。
为了使Hexagon处理器在每个周期内实现大量的工作,指令集被设计成具有以下特性。
静态分组(VLIW)结构
简单依赖指令的静态融合
广泛的复合指令
大量的SIMD和特定应用指令集
为了支持高效的编译,指令集被设计为在寄存器、寻址模式和加载/存储访问大小方面是正交的。
Hexagon处理器支持以下内存寻址模式。
32位绝对值
32位绝对集
带有寄存器偏移的绝对模式
全局相对指针
间接
带偏移的间接
带有寄存器偏移的间接
带有自动递增功能的间接指针(即时或寄存器)。
带自动递增的循环(即时或寄存器)。
带有自动增加寄存器的位反转
比如说:
R2 = memw(##myvariable)
R2 = memw(R3=##myvariable)
R2 = memw(R4<<#3+##myvariable)
R2 = memw(GP+#200)
R2 = memw(R1)
R2 = memw(R3+#100)
R2 = memw(R3+R4<<#2)
R2 = memw(R3++#4)
R2 = memw(R0++M1)
R0 = memw(R2++#8:circ(M0))
R0 = memw(R2++I:circ(M0))
R2 = memw(R0++M1:brev)
寄存器寻址的自动增量使用两个专用的地址修改寄存器M0和M1中的一个(属于控制寄存器的一部分)。
注意 原子内存操作(加载锁定/存储条件)被支持以实现多线程同步。
Hexagon处理器包括以下对定点数据的标量操作:
■ 16位、32位和复数数据的乘法运算
■ 16位、32位和64位数据的加法和减法(有或无饱和度)。
■ 32位和64位数据的逻辑运算(AND, OR, XOR, NOT)。
■ 32位和64位数据的移位(算术和逻辑)。
■最小/最大、否定、绝对值、奇偶校验、常数、旋转。
■ 8位、16位、32位和64位数据的比较
■符号和零扩展(8位和16位到32位,32位到64位)。
■位操作
■谓词操作
Hexagon处理器包括以下对定点数据的向量操作。
乘法(半字、字对半、向量减、双倍乘法)
字和半字数据的加法和减法
字和半字数据的移位(算术和逻辑)。
最小/最大、平均、负平均、绝对差异、绝对值
字、半字和字节数据的比较
减少,无符号字节的绝对差异之和
特殊用途的数据排列(如打包、拼接、洗牌、对齐、饱和、拼接、截断、复数共轭、复数旋转、零扩展)。
注意 某些向量操作支持自动缩放、饱和和舍入。例如,下面的指令执行了一个矢量操作。
R1:0 += vrmpyh(R3:2,R5:4)
t被定义为在一个周期内执行以下操作。
R1:0 += ((R2.L * R4.L) +
(R2.H * R4.H) +
(R3.L * R5.L) +
(R3.H * R5.H)
)
Hexagon处理器包括对浮点数据的以下操作。
加法和减法
乘法(可选择缩放)。
最小/最大/比较
往复/平方根逼近
格式转换
Hexagon处理器支持零开销的硬件循环。比如说:
loop0(start,#3) // loop 3 times
start:
{ R0 = mpyi(R0,R0) } :endloop0
循环指令支持可嵌套的循环,对其使用没有什么限制。
软件分支使用一个预设的分支机制。明确的比较指令产生一个谓词位,然后由条件分支指令测试。比如说:
P1 = cmp.eq(R2, R3)
if (P1) jump end
跳转和子程序调用可以是有条件的,也可以是无条件的,并支持PC-相对和寄存器间接寻址模式。比如说:
jump end
jumpr R1
call function
callr R2
子程序调用指令将返回地址存储在寄存器R31中。子程序的返回是通过这个寄存器用间接跳转指令来完成的。比如说:
jumpr R31 // subroutine return
指令序列可以明确地被分组为数据包,用于并行执行。比如说:
{
R8 = memh(R3++#2)
R12 = memw(R1++#4)
R = mpy(R10,R6):<<1:sat
R7 = add(R9,#2)
}
括号字符用于划分指令包的开始和结束。
包的长度可以是一条到四条指令。不同长度的数据包可以在程序中自由混合。
数据包对允许的指令组合有各种限制。主要的限制是由指令包中的指令类别决定的。
在很多情况下,一个谓词或通用寄存器可以在同一个指令包中生成和使用。这个特点在汇编语言中是通过在指定的寄存器后面加上后缀".new "来表示的。比如说:
在bit位置的 64 位原子变量中切换位。
{
P0 = cmp.eq(R2,#4)
if (P0.new) R3 = memw(R4)
if (!P0.new) R5 = #5
}
{
R2 = memh(R4+#8)
memw(R5) = R2.new
}
某些常见的操作对(加法-累加、移位-加法、去分配法-返回等)可以通过复合指令来完成。使用复合指令可以减少代码大小,提高代码性能。
最常见指令的一个子集(加载、存储、分支、ALU)可以成对打包成单一的32位指令,称为双工指令。双工指令减少了代码大小。
这些指令被分配到特定的指令类。类的重要性在于两个原因:
■只有特定的指令组合可以并行编写(如图1-1所示),而允许的组合是由指令类指定的。
■指令类在逻辑上与指令类型相对应,所以它们是查找特定指令的助记符。
为了支持程序中时间关键部分的有效编码(不需要借助于汇编语言),C语言编译器支持内在因素,用于在C代码中直接表达Hexagon处理器指令。比如说:
int main() {
long long v1 = 0xFFFF0000FFFF0000;
long long v2 = 0x0000FFFF0000FFFF;
long long result;
// find the minimum for each half-word in 64-bit vector
result = Q6_P_vminh_PP(v1,v2);
}
大多数Hexagon处理器指令都定义了内含物。
本节介绍本文件中用于描述 Hexagon 处理器指令的符号惯例。
■指令语法
■寄存器操作数
■数值操作数
注意 这里描述的符号并不出现在实际的汇编语言指令中。它仅用于指定指令的语法和行为。
以下符号用于描述指令的语法:
■指令使用单行字体
■方括号内为可选项目(例如,[:sat],表示饱和度为可选)。
■大括号表示项目的选择(例如,{Rs,#s16},表示可以使用Rs或有符号的16位即期。)
下面的符号描述了指令的语法和行为中的寄存器操作数。
Rds[.elst]
ds字段表示寄存器操作数的类型和位大小(如表1-1所定义)。表1-1 寄存器符号
ds字段的例子(描述指令的语法):
Rd = neg(Rs)
Rd = xor(Rs,Rt)
Rx = insert(Rs,Rtt)
// Rd -> 32-bit dest, Rs 32-bit source
// Rt -> 32-bit second source
// Rx -> both source and dest
ds字段(描述指令行为)的例子:
Rdd = Rss + Rtt // Rdd, Rss, Rtt -> 64-bit registers
可选的elst字段("元素大小和类型 "的简称)在寄存器被用作向量时指定了寄存器的部分内容。它可以指定以下值。
■寄存器中的有符号或无符号的字节、半字或字(如图1-4中定义的)。
■寄存器中的一个位域(如表1-2所定义)。
elst字段的例子:
EA = Rt.h[1]
Pd = (Rss.u64 > Rtt.u64)
Rd = mpyu(Rs.L,Rt.H)
// .h[1] -> bit field 31:16 in Rt
// .u64 -> unsigned 64-bit value
// .L/.H -> low/high 16-bit fields
控制和谓词寄存器使用与一般寄存器相同的符号,但写成Cx和Px(分别)而不是Rx。
表1-3列出了在指令的语法和行为中用于描述数字操作数的符号。
#uN, #sN, 和#mN在指令中指定即时操作数。符号#出现在实际指令中,表示即时操作数。
#rN指定指令中的循环和分支目的地。在这种情况下,#符号不出现在实际指令中;相反,整个#rN符号(包括其后缀:S)被表示为一个循环或分支符号,其数值由汇编器和链接器决定。比如说
call my_proc // 指令示例
后缀:S表示数值中最小的S位是隐含的零位,因此不在指令中编码。
因此不在指令中编码。隐含的零位被称为刻度位。
例如,#s4:2表示一个有符号的即时操作数,由指令中编码的四个位和两个比例位表示。这个操作数的可能值是-32、-28、-24、-20、-16、-12、-8、-4、0、4、8、12、16、20、24、28。
##指定指令中的32位即时操作数(包括循环或分支目的地)。##符号出现在实际指令中,表示操作数。
操作数符号的例子。
Rd = add(Rs,#s16) // #s16 -> 有符号的16位移民值
Rd = memw(Rs++#s4:2) // #s4:2 -> 有符号的4位固定值
调用#r22:2 // #r22:2 – – 按比例的22位PC-rel地址值
Rd = ##u32 // ##u32 -> 无符号32位移民值
注意 当一条指令包含一个以上的即时操作数时,操作数的符号以大写和小写的方式指定(如#uN和#UN),以表示它们在指令编码中的出现。
表1-4列出了Hexagon处理器指令名称中用于指定支持的数据类型的符号。
如需帮助或澄清本文件中的信息,请向高通技术公司提交案例,地址是:https://support.cdmatech.com。
如果您无法访问CDMATech支持网站,请注册访问或发送电子邮件至 [email protected]。