[英]Why RISC-V don't have conditional branch equal with immediate value?
以下是我的 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 指令集中有很多想法,因此更想知道是否有其他方法可以用较少的指令来执行此条件分支。 如果不是,那么没有条件分支的直接变体的原因可能是什么?
指令格式方面,寄存器字段可用于 imm5 值。
指令编码没有那么多空间!
已经有一个直接的——分支目标。
条件分支通常需要很多操作数:两个源,一个条件和一个分支目标。 许多指令集将它们分成两条指令,比较和分支通过条件代码链接在一起。
但是 RISC V 选择避免使用条件代码,因此提供了这两个寄存器源分支。
如果该代码处于紧密循环中,您可以将立即数放入循环之前的寄存器中,并将该指令保存在循环内。
更好的是,您可以使用零寄存器切换到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
指令格式方面,寄存器字段可用于 imm5 值。
是的,这可以工作。 这可能需要一个额外的操作码(或者如果仅限于bne
和beq
,而忽略其他关系,可以将其压缩到现有SB
格式主操作码的func3
中),然后还需要一个额外的指令格式。
代码空间和其他性能改进的价值对我来说是未知的,因为 0 的立即数(可能是最重要的立即数)已经用零寄存器考虑了,并且考虑到li
指令可以移出紧密循环. 然而,那些其他因素(新的操作码/指令格式)会使特别是低端/嵌入式处理器实现(已知对设计人员非常重要)复杂化,以换取(小?)改进。 RISC V 设计允许可扩展性,因此这仍然可以实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.