一、问题描述与解决思路
在32位下,lui/auipc通常用来取一个32位数的高20位,并且是带符号操作,将最高位默认为符号位。那么,取完最高位20位之后,再取低12位的时候,会面临一个补值问题。
假设这个32位内容为正数,lui/auipc取高20位的时候本身没问题,但是后续再对剩余的12位数字进行操作的时候,如果第11位是1,那么这一位会被当成是符号位,就将一个12位的正数变成了一个11位的负数。这种情况之下,lui/aupic和addi的合并操作的计算结果就不对了,就变成了高20位减去了一个低11位负数。正确的结果应该是高20位加上一个正的低12位。焦点就是将本不是符号位的第11位当成了符号位进行 处理。
《Computer Organization and Design》第五版RISCV版中,第114页中也讨论了这个问题:
在例子后面的讨论中提到了这个问题,解决方案是加上一个2的12次方,然后能保证得到一个正确的结果。
这里边的逻辑是这样的:一个12位的正数,它的值等于x11 * 2(11) + x10 * 2(10) + .... + x0 * 2(0)。这里x11指的是第11位上的数字,通常是1或者0,2(11)指的是2的11次方。但是如果这个12位的正数被当成了负数,而负数在这里使用补码表示的,那么它的值就等于 -x11 * 2(11) + x10 * 2(10)+ .... + x0 * 2(0)。加上12位正数和减去