beq
lyszt.net 更详细地介绍了 beq 和其他 RISC-V 指令。
编码格式
描述
beq 让程序做出决定。处理器通常按照指令在列表中出现的顺序执行它们。这个顺序本身无法选择或重复任何东西。分支改变这个顺序。它测试一个条件,如果条件成立,处理器就在不同的位置继续,而不是下一行。所有 if 语句和循环都由分支构建而成。
那个不同的位置由一个标签命名,标签是一个名称后跟一个冒号,用来标记代码中的一个位置,例如示例中的标签 done。beq(相等则分支)比较两个寄存器。当它们持有相同的值时,它跳转到标签标记的位置;当它们不同时,执行继续下一条指令。形式如下所示。
beq rs1, rs2, label
beq 只改变下一条运行的指令。将比较的 yes 或 no 结果存储为数字需要另一条指令,在 slt 页面中描述。
处理器用一个称为程序计数器的寄存器跟踪自己的位置,它保存正在运行的指令的地址。一个被采用的分支会改变该地址,因此下一条指令来自标签。
RISC-V 手册指出,条件分支将其偏移量存储为一个以 2 字节的倍数计数的 12 位值。该偏移量被符号扩展并加到分支指令的地址上,给出正负 4 KiB 的范围,其中 KiB 是 1024 字节。分支指令直接比较两个寄存器,不使用条件码。手册给出的理由是,一条组合的比较并分支指令适合常规流水线,不需要额外的状态或临时寄存器。它还建议软件将最常见的路径保持为直线代码,并预期向后分支被预测为采用,向前分支被预测为不采用,至少在第一次遇到它们时如此。
分支比较两个寄存器,不能取写在指令中的常量,因此像 beq t0, 5, label 这样的形式不存在。要将寄存器与常量比较,先用 li 将常量加载到寄存器中,然后比较这两个寄存器。
li t1, 5 beq t0, t1, done
值 0 不需要加载,因为寄存器 zero 总是持有它。
一种常见用法是将寄存器与 zero(总是持有 0 的寄存器)比较,以询问一个值是否已经到达零。这会结束倒计数循环并检查结果。示例在 a0 倒计数到零时分支到 done。beq 和标签足以构建程序中的每一个决定和循环。
示例
beq a0, zero, done # if a0 == 0, jump to 'done'
