2.3 立即数编码变体
译者:范毅(@beyondskyml)
校对:咧威(@colin4124)
对于处理立即数,还有两种指令格式变体(SB / UJ),如图 2.3 所示。
图中每个立即数子域的标示方式,采用的是生成(符号位扩展)后完整立即数中该子域所在的比特位(imm[x]),而不是像常见的那样,采用其所在的指令立即数字段的比特位。图 2.4 展示了由每种基本指令格式产生的立即数,并使用产生每一位立即数数值的相应指令位(inst[y])来标示。
S 和 SB 格式的唯一区别是,S格式里用来编码分支偏移量的 12 位立即数,在 SB 格式中扩大了一倍(即左移一位,相当于乘2)。这里没有采用传统方式,用硬件把指令中所有立即数所在位左移一位,而是选择固定中间位(imm[10:1])和符号位位置,只把 S 格式中的最低位(inst[7])编码成 SB 格式中的一个高位。
图 2.3: RISC-V 基本指令格式的立即数变种情况。
图 2.4: RISC-V 指令生成的立即数类型。使用构成立即数的相应指令位来标示各个字段。符号位总是 inst[31]。
相似地,U 和 UJ 格式也只有一处不同——20 位的立即数左移 12 位形成 U 立即数,左移 1 位形成 J 立即数。U 和 UJ 格式的立即数在指令中的位置尽可能与其他格式包括二者之间相互重叠。
立即数的符号位扩展是其最为关键的操作之一(尤其是在 RV64I),RISC-V 中所有立即数的符号位总是位于指令的 31 位,从而使符号扩展与指令译码并行展开。
虽然更复杂的实现中也许有单独的加法器计算分支和跳转地址,那么在不同类型的指令间保持相同的立即数位置并无益处,但是我们想要降低最简单的实现方案的硬件成本。通过调换(rotating)B 和 J 立即数编码在指令中相应的位,而不是使用动态的硬件多路选择器给立即数乘 2,我们降低了大约一半的指令信号的输出端数(fanout)以及立即数多路选择器的成本。对于静态或超前编译,乱序的立即数编码增加的时间微不足道。对于动态 JIT (Just in time,即时编译)的指令生成方式,虽然会有小量的额外开销,但是更常见的距离短的(short forward)分支有直接的立即数编码。