在RISC-V中有這樣一條偽指令:
li a0, immediately
可以將任意的32位數(shù)據(jù)或者地址加載到指定的寄存器中
在 RV32I中,它擴展到 lui 和/或 addi
li 何時擴展為 lui 或者 addi呢?又何時擴展為lui 和 addi呢?
我們觀察lui 和 addi 的指令碼即可得出結(jié)果
由上圖可知,lui加載的立即數(shù)為高20位,addi加載的立即數(shù)為低12位
由此得出結(jié)論
- 若 li 加載的立即數(shù)范圍為:0~4096 時,會擴展成 addi 指令
li a0, immediately ? addi a0, x0, imme
- 若 li 加載的立即數(shù)范圍超過4096時,會擴展成 lui 指令 和 addi 指令
li a0, immediately 擴展成
1、lui a0, (immediately >> 12)
2、addi a0, a0, (immediately & 0xFFF) - 若 li 加載的立即數(shù)范圍超過4096時,并且低12位為0,會擴展成 lui 指令
li a0, immediately
擴展成
lui a0, (immediately >> 12)
接上文,觀察 lui指令、addi指令 會得到這個結(jié)果:lui指令加載的立即數(shù)為無符號,無需注意。addi指令加載的為有符號數(shù),這個需要考慮一下立即數(shù)的符號位
假如我們要加載大立即數(shù)到指定的寄存器,需要考慮兩種情況
1、第11位為0
第11位為0,則指令:li a0, immediate
會直接擴展成:
lui a0, immediate >> 12
addi a0, a0, (immediate & 0xFFF)
2、第11位為1
第11位為1,此時 li a0, immediate
就不會擴展成
lui a0, immediate >> 12
addi a0, a0, (immediate & 0xFFF)
而是擴展成
lui a0, ((immediate >> 12) + 1)
addi a0, a0, ((immediate & 0xFFF) - 2^12)
解釋一下:
addi指令所加載的立即數(shù)的第11位為1時,這個立即數(shù)是符號擴展的,因此加數(shù)將為負數(shù)。這意味著除了添加常量的最右邊11位
之外,我們還需要減去2^12。為了彌補這個錯誤,只需將lui 加載的常量添加一個1,因為 lui 常量縮小了 2 ^12倍文章來源:http://www.zghlxwxcb.cn/news/detail-405257.html
例如:將 0xE76 加載到寄存器a0中
答:文章來源地址http://www.zghlxwxcb.cn/news/detail-405257.html
lui a0, 0x01
addi a0, a0, (0xE76 - 4096)
代碼實現(xiàn)
#define immediate XXXX
uint32_t MSB, LSB;
MSB = immediate >> 12;
LSB = immediate & 0xFFF;
if (MSB == 0) {
if (LSB & 0x800) {
asm volatile("lui a0, 0x01");
asm volatile("addi a0, a0, LSB - 4096");
} else {
asm volatile("addi a0, x0, LSB");
}
} else {
if (LSB & 0x800) {
asm volatile("lui a0, MSB + 0x01");
asm volatile("addi a0, a0, LSB - 4096");
} else {
asm volatile("lui a0, MSB");
asm volatile("addi a0, x0, LSB");
}
}
到了這里,關(guān)于【RISC-V】 li指令的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!