Hexagon处理器使用基于比较指令的条件执行模型在四个8位断言寄存器(P0-P3)之一中设置断言位。这些断言位可以用于有条件地执行某些指令。
条件标量运算只检查断言寄存器中的最低有效位,而条件向量运算检查寄存器中的多个位。
分支指令是断言寄存器的主要使用者。
标量断言是8位值,在条件指令中用于表示
真值:
Hexagon处理器提供四个8位断言寄存器P0-P3来保存标量断言(第2.2.5节)。这些寄存器由生成断言的指令,并由断言使用指令检查
以下指令生成标量断言:
表6-1列出了标量断言生成指令。
注:其中一个比较指令(cmp.eq)包括一个变量,该变量存储通用寄存器而非断言寄存器中的二进制断言值(0或1)
某些指令可以基于标量断言的值有条件地执行(或者指定标量断言作为其操作的输入)。
使用标量断言的条件指令只检查断言值的最低有效位。在最简单的情况下,该位值直接决定是否执行指令:
1表示指令已执行
0表示未执行指令
如果条件指令包含运算符!在其断言表达式中,逻辑位值的求反决定是否执行指令。
条件指令用带指令前缀的汇编语言表示“if(pred\u expr)”,其中pred\u expr指定断言表达式。例如:
if (P0) jump target // jump if P0 is true
if (!P2) R2 = R5 // assign register if !P2 is true
if (P1) R0 = sub(R2,R3) // conditionally subtract if P1
if (P2) R0 = memw(R2) // conditionally load word if P2
以下指令可用作条件指令:
当执行条件加载或存储时,断言表达式为false,则指令被取消(包括可能发生的任何异常)。例如,如果条件加载使用内存权限冲突的地址和断言表达式为false,不会执行加载,也不会引发异常。
mux指令接受断言作为其基本操作数之一:
Rd = mux(Ps,Rs,Rt)
mux根据Ps中的最低有效位选择Rs或Rt。如果最低有效位Ps中的位为1,Rd设置为Rs,否则设置为Rt。
如果数据包中的多个比较指令写入同一断言寄存器,则结果是单个比较结果的逻辑与。例如:
{
P0 = cmp(A) // if A && B then jump
P0 = cmp(B)
if (P0.new) jump:T taken_path
}
要执行相应的OR操作,可以使用以下说明计算现有比较的否定(使用德摩根定律):
Auto和断言有以下限制:
注:从断言寄存器到断言寄存器的寄存器传输具有与比较指令相同的自动和行为
Hexagon处理器可以在同一条指令中生成和使用标量断言数据包(第3.3节)。此功能在汇编语言中通过附加指定断言寄存器的后缀“.new”。例如:
if (P0.new) R3 = memw(R4)
要了解如何使用dot new断言,请考虑以下C语句和编译器从中生成的相应汇编代码:
C statement
if (R2 == 4)
R3 = *R4;
else
R5 = 5;
Assembly code
{
P0 = cmp.eq(R2,#4)
if (P0.new) R3 = memw(R4)
if (!P0.new) R5 = #5
}
以下条件适用于使用dot新断言:
断言必须由同一数据包中的指令生成。这个汇编程序通常强制执行此限制,但如果处理器执行数据包如果违反此限制,则执行结果未定义。
单个数据包可以包含新断言和正常断言。这个范式检查断言寄存器中的旧值,而不是新产生的价值。例如
{
P0 = cmp.eq(R2,#4)
if (P0.new) R3 = memw(R4) // use newly-generated P0 value
if (P0) R5 = #5 // use previous P0 value
}
指令包中的两条指令不应写入同一目标寄存器(第3.3.5节)。此规则的一个例外是,如果这两条指令是有条件的,并且当数据包为时,其中只有一个断言表达式值为true执行。
例如,只要P2和P3都不计算为,以下数据包就有效执行数据包时为true
{
if (P2) R3 = #4 // P2, P3, or both must be false
if (P3) R3 = #7
}
由于断言值在运行时发生变化,程序员负责确保这些数据包在程序执行期间始终有效。如果无效,则处理器执行以下操作:
断言寄存器也用于条件向量运算。与标量不同
断言、向量断言包含由向量生成的多个真值
断言生成操作。
例如,向量比较指令比较向量的每个元素并赋值
将结果与断言寄存器进行比较。断言向量中的每一位都包含一个真值
值,指示向量指令执行的单独比较的结果。
矢量多路复用指令使用矢量断言有选择地合并两个指令中的元素
将向量分离为单个目标向量。此操作有助于启用
具有控制流(即分支)的回路矢量化。
下面几节介绍了使用断言的向量指令。
向量比较指令输入两个64位向量,对其执行单独的比较每对向量元素,并生成一个断言值,其中包含真值。
图6-1显示了向量字节比较的示例
在图6-1中,比较了两个64位字节向量(包含在Rss和Rtt中)。
结果作为向量断言分配给目标寄存器Pd。
在图6-1所示的示例向量断言中,请注意,每隔一个比较结果在断言中为true(即1)。
图6-2显示了向量半字比较如何生成向量断言。
在图6-2中,比较了半字的两个64位向量。结果已分配作为目标寄存器Pd的向量断言。
因为向量半字比较只产生四个真值,所以每个真值是在生成的向量断言中编码为两位
矢量多路复用指令用于有条件地从两个矢量中选择元素。
该指令将两个源向量和一个断言寄存器作为输入。对于中的每个字节
在向量中,断言寄存器中的对应位用于从
两个输入向量。组合结果写入目标寄存器。
图6-3显示了矢量多路复用指令的操作。
表6-2定义了矢量多路复用指令
更改多路复用指令中源操作数的顺序可以同时启用要形成的结果。例如:
R1:0=vmux(P0,R3:2,R5:4)//如果为true,则从R3:2中选择字节
R1:0=vmux(P0,R5:4,R3:2)//如果为false,则从R3:2中选择字节
注意:通过复制由字或半字比较生成的断言位矢量多路复用指令可用于选择字或半字。
考虑以下C语句:
for (i=0; i<8; i++) {
if (A[i]) {
B[i] = C[i];
}
}
假设字节数组,该代码可以矢量化如下
R1:0 = memd(R_A) // R1:0 holds A[7]-A[0]
R3 = #0 // clear R3:2
R2 = #0
P0 = vcmpb.eq(R1:0,R3:2) // compare bytes in A to zero
R5:4 = memd(R_B) // R5:4 holds B[7]-B[0]
R7:6 = memd(R_C) // R7:6 holds C[7]-C[0]
R3:2 = vmux(P0,R7:6,R5:4) // if (A[i]) B[i]=C[i]
memd(R_B) = R3:2 // store B[7]-B[0]
六边形处理器提供了一组操作和移动操作断言寄存器。
表6-3列出了断言寄存器指令。
注:这些指令属于指令类CR。
断言寄存器可以在通用寄存器之间传输单独或作为寄存器四倍(第2.2.5节)