为什么RISC-V没有等于即时值的条件分支?



以下是我的RISC-V汇编项目中最常见的条件分支代码。

li a0, UART1_BASE;
lw t0, UART_INTR_PEND_OFFSET(a0); // Read UART interrupt pending status
andi t0, t0, 1;
li t1, 1; // IMM LOAD
beq t0, t1, LB_process_tx; // UART Tx interrupt 
// else UART rx interrupt 

如果分支相等指令有直接的变体(如beqi t0, 1, LB_process_tx),则可以避免IMM LOAD指令li t1, 1。我没有找到条件分支的直接变体。如果我说错了请指正。

我很清楚,在RISC-V指令集中已经有了很多想法,因此更感兴趣的是知道是否有其他方法可以用更少的指令来执行这个条件分支. 如果没有,没有条件分支的直接变体背后的原因可能是什么?

指令格式方面,用于寄存器的字段可用于im5值。

指令编码没有那么多空间!

已经有一个直接的分支目标。

条件分支通常需要许多操作数:两个源、一个条件和一个分支目标。许多指令集将它们分成两个指令,通过条件码进行比较和分支连接在一起。

但是RISC V选择避免条件码,因此提供了这两个寄存器源分支。

如果代码是紧循环,可以在循环前将immediate放入寄存器,并将该指令保存在循环中。

更好的是,您可以使用零寄存器切换到bne,而不是与该代码序列中的1进行比较,以消除li

原始:

andi t0, t0, 1;
li t1, 1; // IMM LOAD
beq t0, t1, LB_process_tx; // UART Tx interrupt 

由于上面的andi操作将结果限制为0或1,因此我们可以使用bne来检查是否为零,而不需要li:

andi t0 t0 1
bne t0, zero, LB_process_tx  # compare for != 0

,或者这里andi结果限制为0或2,我们仍然可以使用bne:

andi t0, t0, 2
bne t0, zero, LB_process_rx

指令格式方面,寄存器字段可用于im5值。

是的,那可以工作。这可能需要一个额外的操作码(或者如果仅限于bnebeq而忽略其他关系,则可以压缩到现有SB格式主操作码的func3中),然后还需要一个额外的指令格式。

代码空间中的值和其他性能改进对我来说是未知的,因为直接值0(可能是最重要的直接值)已经用零寄存器计算过了,并且考虑到li指令可以从紧循环中移出。然而,那些其他因素(新的操作码/指令格式)会使低端/嵌入式处理器实现(对设计者来说非常重要)变得更加复杂。RISC V的设计允许可扩展性,所以这仍然可以想象实现。

最新更新