在RISC-V中有這樣一條偽指令:
li a0, immediately
可以將任意的32位數(shù)據(jù)或者地址加載到指定的寄存器中
在 RV32I中,它擴(kuò)展到 lui 和/或 addi
li 何時(shí)擴(kuò)展為 lui 或者 addi呢?又何時(shí)擴(kuò)展為lui 和 addi呢?
我們觀察lui 和 addi 的指令碼即可得出結(jié)果
由上圖可知,lui加載的立即數(shù)為高20位,addi加載的立即數(shù)為低12位
由此得出結(jié)論
- 若 li 加載的立即數(shù)范圍為:0~4096 時(shí),會(huì)擴(kuò)展成 addi 指令
li a0, immediately ? addi a0, x0, imme
- 若 li 加載的立即數(shù)范圍超過(guò)4096時(shí),會(huì)擴(kuò)展成 lui 指令 和 addi 指令
li a0, immediately 擴(kuò)展成
1、lui a0, (immediately >> 12)
2、addi a0, a0, (immediately & 0xFFF)
- 若 li 加載的立即數(shù)范圍超過(guò)4096時(shí),并且低12位為0,會(huì)擴(kuò)展成 lui 指令
li a0, immediately
擴(kuò)展成
lui a0, (immediately >> 12)
接上文,觀察 lui指令 、addi指令 會(huì)得到這個(gè)結(jié)果:lui指令加載的立即數(shù)為無(wú)符號(hào),無(wú)需注意。addi指令加載的為有符號(hào)數(shù),這個(gè)需要考慮一下立即數(shù)的符號(hào)位
假如我們要加載大立即數(shù)到指定的寄存器,需要考慮兩種情況
1、第11位為0
第11位為0,則指令:li a0, immediate
會(huì)直接擴(kuò)展成:
lui a0, immediate >> 12
addi a0, a0, (immediate & 0xFFF)
2、第11位為1
第11位為1,此時(shí) li a0, immediate
就不會(huì)擴(kuò)展成
lui a0, immediate >> 12
addi a0, a0, (immediate & 0xFFF)
而是擴(kuò)展成
lui a0, ((immediate >> 12) + 1)
addi a0, a0, ((immediate & 0xFFF) - 2^12)
解釋一下:
addi指令所加載的立即數(shù)的第11位為1時(shí),這個(gè)立即數(shù)是符號(hào)擴(kuò)展的,因此加數(shù)將為負(fù)數(shù)。這意味著除了添加常量的最右邊11位
之外,我們還需要減去2^12。為了彌補(bǔ)這個(gè)錯(cuò)誤,只需將lui 加載的常量添加一個(gè)1,因?yàn)?lui 常量縮小了 2 ^12倍
例如:將 0xE76 加載到寄存器a0中
答:
lui a0, 0x01
addi a0, a0, (0xE76 - 4096)
代碼實(shí)現(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)注
關(guān)注
31文章
5254瀏覽量
119214 -
指令
+關(guān)注
關(guān)注
1文章
598瀏覽量
35508 -
RISC-V
+關(guān)注
關(guān)注
44文章
2142瀏覽量
45713
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論