i基准指令集 mips_ARM/MIPS/PowerPC/RISC-V 指令集快速入门
這里所介紹的指令集架構(gòu)均屬于 RISC,相比 CISC 更簡(jiǎn)單。但是 ARM 比較特殊,因?yàn)樗鳛橐粋€(gè) RISC 架構(gòu)竟然有 push/pop 指令……
ARMv7
ARM 指令集從舊到新有 ARMv6、ARMv7、ARMv7s、ARMv8,使用新指令集的芯片也能支持舊的指令集,但是無(wú)法發(fā)揮出較好的性能。同時(shí)要注意,指令集版本不同的靜態(tài)庫(kù)是不能一起使用的。
ARM 有兩種工作狀態(tài),ARM 狀態(tài)的指令長(zhǎng)度是 32 位的,Thumb 狀態(tài)的指令長(zhǎng)度是 16 位的(從 ARMv6-T2 開(kāi)始引入的 Thumb-2 指令集也支持 32 位的指令,具有 .w 后綴)
使用 Thumb 指令集可以得到較小的二進(jìn)制文件,但是可以訪問(wèn)的寄存器更少,產(chǎn)生的指令數(shù)量更多,性能會(huì)有損失。
寄存器
Register...
r0函數(shù)返回值或函數(shù)參數(shù)
r1~r3函數(shù)參數(shù),更多參數(shù)使用棧傳遞
r4~r10臨時(shí)變量
r11函數(shù)棧幀?FP(類(lèi)似于?EBP?寄存器)
r12內(nèi)部過(guò)程調(diào)用寄存器?IP
r13棧指針?SP
r14鏈接寄存器?LR,用于存儲(chǔ)將要跳轉(zhuǎn)到的地址
r15程序計(jì)數(shù)器?PC
Cortex-M 含有兩個(gè)棧指針寄存器(SP),分別為 PSP(Process SP)和 MSP(Main SP)。
ARM 指令
指令結(jié)構(gòu)為 MNEMONIC{S}{cond} {Rd}, Operand1, Operand2
如果指令后加了 S,將依據(jù)計(jì)算結(jié)果更新當(dāng)前程序狀態(tài)寄存器 CPSR 中相應(yīng)的標(biāo)志。
cond 表示執(zhí)行條件,見(jiàn)下表。
擴(kuò)展助記符意義(整形)意義(浮點(diǎn))條件
EQ相等相等Z==1
NE不相等不相等或無(wú)序(即至少有一個(gè) NaN)Z==0
CS/HS進(jìn)位置位/無(wú)符號(hào)高于等于大于等于或無(wú)序C==1
CC/LO進(jìn)位復(fù)位/無(wú)符號(hào)低于小于C==0
MI減法、負(fù)數(shù)小于N==1
PL加法、非負(fù)數(shù)大于等于,或無(wú)序N==0
VS溢出置位無(wú)序V==1
VC溢出復(fù)位不無(wú)序V==0
HI無(wú)符號(hào)高于大于或無(wú)序C==1 且 Z==0
LS無(wú)符號(hào)不高于小于或相等C==0 或 Z==1
GE有符號(hào)大于等于大于等于N==V
LT有符號(hào)小于小于或無(wú)序N!=V
GT有符號(hào)大于大于Z==0 且 N==V
LE有符號(hào)小于等于小于等于或無(wú)序Z==1 或 N!=V
AL(default)無(wú)條件無(wú)條件
第三個(gè)操作數(shù)可以是寄存器,也可以是要進(jìn)行的移位操作。可能的操作有 LSL/LSR/ASR/ROR/RRX,其中 RRX 表示右移一位,最高位由 APSR 寄存器的狀態(tài)位 C 填充,移出的位給狀態(tài)位 C。
Mnemonic...
mov復(fù)制寄存器。例如 MOV R0,R2,LSL #3 表示把 R2 左移 3 位后傳給 R0。
lsl/lsr/asr/ror邏輯左移,邏輯右移,算數(shù)右移,循環(huán)右移
push把立即數(shù)、單個(gè)寄存器,多個(gè)寄存器壓棧。多個(gè)寄存器按從右到左壓棧
pop出棧到單個(gè)寄存器或多個(gè)寄存器(從左到右的順序)
ldr/strldr 從內(nèi)存中讀 32 位數(shù)據(jù),str 寫(xiě) 32 位數(shù)據(jù)到內(nèi)存。如 ldr r1, [r2, #0x10] 即 r1 = *(r2+0x10);str r1, [r2, #0x01] 即 *(r2+1)=r1。相應(yīng)地,讀寫(xiě) 16 位時(shí) ldrh/strh;8 位時(shí) ldrb/strb。例如 ldrneh 即不相等時(shí)讀半字。
swp交換值,可用于實(shí)現(xiàn)信號(hào)量
b/blb 跳轉(zhuǎn),bl 跳轉(zhuǎn)并把下一條指令地址存儲(chǔ)到 lr
bx/blx Rm跳轉(zhuǎn)并切換狀態(tài)。由于指令是 2 或 4 字節(jié)對(duì)齊的,地址的最低位一定是 0,故若?Rm & 0x01==1?則令 CPSR.T=1,把目標(biāo)地址解釋為 Thumb 代碼;否則令?CPSR.T=0,目標(biāo)地址解釋為 ARM 代碼
add/sub加減法,更新標(biāo)志位
sbc帶借位減法,Rd = ~Ra + Rb + CPSR.C
cmp比較兩個(gè)寄存器或一個(gè)立即數(shù)(使用減法)并更新標(biāo)志位
tst/teq測(cè)試相等
mul/mla/umullmul 乘法,mla 乘加,即 Ra*Rb+Rc,umull 64 位乘法
svc/swi系統(tǒng)調(diào)用
and/orr/eor按位與,按位或,按位異或
幾個(gè) SIMD 指令:
Mnemonic...
ldmib/stmib/ldmdb/stmdbb 表示存儲(chǔ)器指針在保存/讀取第一個(gè)值之前更新;i 表示更新方式為增加,d 表示更新方式為減少
ldmfa/stmfa/ldmfd/stmfd存儲(chǔ)器指針為 SP 時(shí),就等價(jià)于該指令。f 表示堆棧指針指向內(nèi)含有效數(shù)據(jù)項(xiàng)的最高地址;a 表示堆棧往高地址增長(zhǎng),d 表示堆棧往低地址增長(zhǎng)
ldmea/stmea/ldmed/stmede 表示堆棧指針指向堆棧的第一個(gè)空位置 ;a 表示堆棧往高地址增長(zhǎng),d 表示堆棧往低地址增長(zhǎng)。
協(xié)處理器指令格式:
MRC/MCR {cond} coproc,opcode1,Rd,CRn,CRm{,opcode2}
MCR:從寄存器到協(xié)處理器
MRC:從協(xié)處理器到寄存器
coproc:協(xié)處理器名稱(chēng),p0~p15
MSR:從寄存器到狀態(tài)寄存器,如 MSR CPSR,R0
MRS:從狀態(tài)寄存器到寄存器,如 MRS R2,SPSR
中斷
Cortex-A 處理器發(fā)生中斷時(shí),先跳轉(zhuǎn)進(jìn) IRQ 入口,再通過(guò)軟件判斷是由哪個(gè)中斷源觸發(fā),獲得相對(duì)應(yīng)的中斷服務(wù)程序(ISR)的地址。而 Cortex-M 處理器發(fā)生中斷時(shí),CPU 自動(dòng)從中斷向量表中尋找相應(yīng)的中斷服務(wù)程序并跳轉(zhuǎn)。
鏈接寄存器(LR)的數(shù)值會(huì)被更新為 EXC_RETURN 值(詳細(xì)含義可自行搜索)。然后硬件自動(dòng)將 r0, r1, r2, r3, r12, lr, pc, psr 寄存器依次入棧,同時(shí)更新 psp 寄存器。中斷處理函數(shù)結(jié)束時(shí),通過(guò) bx lr 指令觸發(fā)中斷返回,處理器將自動(dòng)保存的寄存器值從棧上彈出并恢復(fù)給相應(yīng)的寄存器。
svc 指令用于系統(tǒng)調(diào)用,如 svc #0x900004 調(diào)用 sys_write
另一種方法是把編號(hào)傳給 r7(如 4 為 sys_write),再使用 swi 0 進(jìn)行調(diào)用。
MIPS32
寄存器
Register NumberName...
0zero它總是返回零,對(duì)其寫(xiě)入也沒(méi)有效果
1at匯編器臨時(shí)寄存器,用于加載 16 位以上的大常數(shù)使用
2-3v0,v1函數(shù)返回值,對(duì)于 64 位的返回值,兩個(gè)寄存器都要用到
4-7a0-a3函數(shù)調(diào)用參數(shù),更多參數(shù)使用棧傳遞
8-15t0-t7無(wú)需保存的臨時(shí)變量
16-23s0-s7需要在當(dāng)前函數(shù)返回之前,恢復(fù)其本來(lái)值的臨時(shí)變量
24,25t8-t9無(wú)需保存的臨時(shí)變量
26k0發(fā)生中斷時(shí),在中斷處理過(guò)程中用作臨時(shí)變量
27k1用于中斷嵌套的深度計(jì)數(shù)器。也可作為臨時(shí)變量
28gp一個(gè)全局指針,可以用于訪問(wèn)一些全局變量。沒(méi)有特定的用法
29sp棧指針
30s8/fp棧幀指針,也可作為需要維護(hù)值的臨時(shí)變量
31ra保存了函數(shù)的返回地址,類(lèi)似于?lr
此外還有不可直接操作的 lo、hi 寄存器,在運(yùn)算指令中會(huì)用到。
指令
Mnemonic...
lb/lh/lw從存儲(chǔ)器中讀取一個(gè) byte/half word/word 的有符號(hào)數(shù)到寄存器中。lb r1, 0(r2) 即 r1=(signed int)*(char*)(r2+0)
lbu/lhu從存儲(chǔ)器中讀取一個(gè) byte/half word 的無(wú)符號(hào)數(shù)到寄存器中。lhu r1, 0(r2) 即 r1=(unsigned int)*(short*)(r2+0)
sb/sh/sw把一個(gè) byte/half word/word 的數(shù)據(jù)從寄存器存儲(chǔ)到存儲(chǔ)器中。如 sb r1, 0(r2) 即 *(char*)(r2+0)=(char)r1
llo/lhi加載低半字/加載高半字,lhi r1,2 即把 r1 的高半字設(shè)為 2
lui把一個(gè) 16 位的立即數(shù)填入到寄存器的高 16 位,低 16 位補(bǔ)零。i 表示立即數(shù)
mflo/mfhi/mtlo/mthi讀寫(xiě) lo、hi 寄存器,mflo r1 即 r1=lo,mthi r1 即 hi=r1
add/addu把兩個(gè)定點(diǎn)寄存器的內(nèi)容相加 add r1,r2,r3 即r1=r2+r3;u 為不帶符號(hào)加
addi/addiu把一個(gè)寄存器的內(nèi)容加上一個(gè)立即數(shù) add r1,r2,#3 即 r1=r2+3;u 為不帶符號(hào)加
sub/subu把兩個(gè)定點(diǎn)寄存器的內(nèi)容相減 sub r1,r2,r3 即 r1=r2-r3
div/divu兩個(gè)定點(diǎn)寄存器的內(nèi)容相除 div r1,r2 即 lo=r1/r2; hi=r1%r2
mult/multu兩個(gè)定點(diǎn)寄存器的內(nèi)容相乘 mult r1,r2 即 hi:lo=r1*r2
and/andi與運(yùn)算,兩個(gè)寄存器中的內(nèi)容相與 and r1,r2,r3 即 r1=r2&r3
or/ori或運(yùn)算,or r1,r2,r3 即 r1=r2|r3
nor或非運(yùn)算,nor r1,r2,r3 即 r1=~(r2|r3)
xor/xori異或運(yùn)算,xor r1,r2,r3 即 r1=r2^r3
beq/beqz/bnez/bne條件轉(zhuǎn)移,eq 相等,z 零,ne 不等。beq r1,r2,label 即 r1 等于 r2 時(shí)跳轉(zhuǎn)。bnez r1,label 即 r1 非 0 時(shí)跳轉(zhuǎn)
bgtz/blez條件轉(zhuǎn)移,gt 大于,le 小于等于
j/jr/jal/jalrj 相對(duì)跳轉(zhuǎn),jr 使用寄存器絕對(duì)跳轉(zhuǎn),jal 把下一條指令地址給 ra 并相對(duì)跳轉(zhuǎn),jalr 把下一條指令地址給 ra 并使用寄存器絕對(duì)跳轉(zhuǎn)
sll/sllv邏輯左移 sll r1,r2,#2,即 r1=r2<<2
sra/srav算數(shù)右移 sra r1,r2,#2 即 r1=r2>>2
srl/srlv邏輯右移 srlv r1,r2,r3 即 r1=r2>>>r3
slt/uslt/slti/sltiuSet if Less Than,slt r1,r2,r3 如果 r2 的值小于 r3,那么設(shè)置 r1 的值為 1,否則設(shè)置 r1 的值為 0
mov/movz/movn復(fù)制寄存器 mov r1,r2;movz r1,r2,r3 即 r3 為零則復(fù)制 r2 到 r1;movn 即 r3 為負(fù)時(shí)復(fù)制
nop空指令
trap根據(jù)地址向量轉(zhuǎn)入管態(tài)
eret/rfe從異常中返回到用戶態(tài)
syscall把系統(tǒng)調(diào)用號(hào)傳給 v0,把參數(shù)傳給 a0~a3,然后使用 syscall 進(jìn)入內(nèi)核態(tài)
MIPS 有一個(gè)特色:分支延遲槽(branch delay slot)。它的意思是,當(dāng)遇到分支指令時(shí)(即 j/jr/jal/jalr),該分支指令的下一條指令一定會(huì)被執(zhí)行。因此 jal 和 jalr 所設(shè)置的 ra 寄存器的值,實(shí)際上是分支指令所在地址 +8,而非 +4。這一點(diǎn)在調(diào)試的時(shí)候需要尤其注意。
此外,在 DIV、DIVU、MULT、MULTU 指令之后,在新的結(jié)果寫(xiě)入 HI 或 LO 之前,必須先用 MFHI 、MFLO 將 HI、LO 讀出。否則兩次連續(xù)對(duì) HI、LO 的寫(xiě)入會(huì)導(dǎo)致下次讀取時(shí)產(chǎn)生不可預(yù)料的值。
中斷
發(fā)生中斷時(shí),處理器把引發(fā)異常的指令地址傳給 CR0 中的 EPC 寄存器,把 pc 的值設(shè)置為 0x8000 0180,把異常原因傳給 CR0 中的 Cause 寄存器。然后在異常處理程序中使用 mfepc 指令(等價(jià)于 mfc0 R, EPC)將 EPC 的值賦給 k0;使用 mfco 指令把異常原因讀出(等價(jià)于 mfc0 R, Cause)。而且在使用這兩個(gè)指令時(shí),需要多加一個(gè) nop 指令以等待其完成。
對(duì)于 MIPS I 和 MIPS II 處理器,從異常返回時(shí),要到 EPC 所指向的地址處繼續(xù)執(zhí)行,并使用 rfe 指令切換回用戶態(tài)(SR 寄存器),匯編指令為:
mfc0 k0, epc
jr k0
rfe
這里 jr 和 rfe 是一起執(zhí)行的。而在 MIPS III 中只需要一條 eret 指令就可以了。
修改 CR0 使用 mtc0 指令,注意 CR0 只能在內(nèi)核態(tài)下訪問(wèn)。
浮點(diǎn)數(shù)
使用 lwc1 把一個(gè) 32 位字從存儲(chǔ)器加載到 CR1,然后可以進(jìn)行運(yùn)算:add.s、add.d、sub.s、sub.d、mul.s、mul.d、div.s、div.d。其中 s 表示單精度,d 表示雙精度。最后使用 swc1 把一個(gè) 32 位字從 CR1 保存到存儲(chǔ)器。
PowerPC 405
寄存器
通用寄存器 r0~r31:
r1 用作棧指針 sp,r3 用作返回值。
函數(shù)參數(shù)從左往右依次使用 r3,r4,r5,r6…傳遞,也可以用棧傳遞。
函數(shù)內(nèi)部臨時(shí)變量依次使用 r31,r30,r29,r28…,而且函數(shù)需要維護(hù) r3~r31 原本的值,在函數(shù)返回時(shí)恢復(fù)到進(jìn)入時(shí)的狀態(tài)。
定點(diǎn)數(shù)異常寄存器(Fixed-Point Exception Register,XER)反映算術(shù)操作的溢出 XER[OV]、進(jìn)位 XER[CA] 和總溢出(Summary Overflow)XER[SO]。
條件寄存器 CR 在一些條件轉(zhuǎn)移指令時(shí)會(huì)用到。它分為 8 個(gè) 4bit 組,依次為 CR0~CR7,其比特位含義如下:
0 1 2 3
| LT | GT | EQ | SO |
指令集
Mnemonic...
addi rD, rA, SIMM先把 SIMM 進(jìn)行符號(hào)擴(kuò)展到 32 位,如果 rA 為 r0 則直接傳給 rD,否則加上 rA 的值傳給 rD
addis rD, rA, SIMM把 SIMM 低位補(bǔ) 16 個(gè) 0,如果 rA 為 r0 則直接傳給 rD,否則加上 rA 的值傳給 rD
lis rD, SIMMaddis rD, 0, SIMM 的別名(偽指令)
li rD, SIMMaddi rD, 0, SIMM 的別名
la rD, d(rA)addi rD, rA, d 的別名
mr rA, rSor rA, rS, rS 的別名
nopori,0,0,0 的別名
lwz rD d(rR)rD=*(rR+(singned int)d)
stw rD d(rR)*(rR+(signed int)d)=rD
mtlr/mtctr把寄存器的值傳給 LR 寄存器或 CTR 寄存器,實(shí)際上是 mfspr 指令的別名
b/ba/bctr/blr/bl/bctrl/blrl無(wú)條件跳轉(zhuǎn),a 表示無(wú)條件跳轉(zhuǎn),ctr 表示跳轉(zhuǎn)到 CTR 寄存器指定的位置,lr 表示跳轉(zhuǎn)到 LR 寄存器指定的位置;再加 l 表示并把下一條指令的地址 賦給 lr
blt/ble/beq/bge/bgt/bne條件跳轉(zhuǎn)。這些指令助記符后同樣可以加 a、lr、ctr 并再加 l。如 beqctrl 表示相等則跳轉(zhuǎn)到 ctr 處并更新 lr
cmpw/cmpwi/cmplw/cmplwi比較字 w 或邏輯字 lw,并更新特定的 CR 域(默認(rèn) CR0)
sraw/srawi算數(shù)右移
srw/srwi/slw/slwi邏輯右移、邏輯左移
注意上表的 SIMM 是帶符號(hào)地從 16 位擴(kuò)展到 32 位,例如 00AE0000+(signed short)AAD0 得到 00ADAAD0(舍去進(jìn)位的 1)。
64 位整數(shù)的加減法對(duì)應(yīng)如下指令:
addc r8,r6,r4 # 低位字相加,記錄進(jìn)位 XER[CA]
adde r7,r5,r3 # 高位字相加,使用前面的進(jìn)位
---
subfc r8,r6,r4 # 減去低位字,記錄借位 XER[CA]
subfe r7,r5,r3 # 減去高位字,使用前面的借位
最終效果就是 (r7:r8)=(r3:r4)±(r5:r6)。
CR0~CR7 都可用于反映指令的結(jié)果。定點(diǎn)數(shù)運(yùn)算指令如 addic.、andi.、andis. 后面的小數(shù)點(diǎn) . 表示它會(huì)更新 CR0 反映他們的結(jié)果,如果沒(méi)有這個(gè)點(diǎn),則只會(huì)更新 XER。更新方式為,把結(jié)果與 0 進(jìn)行比較,更新 CR0 的高 3bit,然后把 XER 的 SO 位復(fù)制到 CR0 的 SO 位。此外 CR1 還可用作浮點(diǎn)操作的結(jié)果(PPC 405 不支持)。
函數(shù)調(diào)用約定
…調(diào)用方傳參,參數(shù)放到 r3
bl func跳轉(zhuǎn)到 func,把下一條指令地址放到lr寄存器
stwu r1, -0xF8(r1)相當(dāng)于 *(sp-F8h)=sp,然后 sp-=F8h。這個(gè)減去的值叫做 back_chain
mflr r0把 lr 寄存器賦給 r0
stw r31, 0xF8-4(r1)把進(jìn)入時(shí)的寄存器值備份到棧上
stw r0, 0xF8+4(r1)把返回地址保存到棧上,方便后續(xù)用 bl 調(diào)用別的函數(shù)
根據(jù)以上過(guò)程,可以得出此時(shí)棧的情況(上面是低地址,下面是高地址)
地址保存的值
sp棧基地址,進(jìn)入時(shí)的 sp,其實(shí)就是 sp+F8h
sp+4分析一下可以發(fā)現(xiàn),如果該函數(shù)再調(diào)用別的函數(shù),那么LR 存到這里
sp+8局部變量。有時(shí)也作為棧傳遞的參數(shù)
……
sp+F8h-8備份進(jìn)入時(shí)的 r30
sp+F8h-4備份進(jìn)入時(shí)的 r31
sp+F8h分析一下可以發(fā)現(xiàn),應(yīng)當(dāng)是調(diào)用者的棧基地址,即sp+F8h+??
sp+F8h+4返回地址*
函數(shù)返回過(guò)程如下:
lwz r0, F8h+4(r1)把棧上的返回地址讀到 r0
mtlr r0把 r0 賦給 lr
lwz r31, F8h-4(r1)把進(jìn)入時(shí)備份的值恢復(fù)給 r31
……
addi r1, r1, F8h恢復(fù)堆棧指針
blrjmp lr
Snippet
下面給出一些匯編指令的化簡(jiǎn)結(jié)果,具體細(xì)節(jié)可以參考指令手冊(cè)。
匯編指令對(duì)應(yīng)的 C 代碼
subfic rA, rB, 0
adde rC, rA, rBrC = (rB ? 0 : 1)
addic rA, rB, -1
subfe rC, rA, rBrC = (rB ? 1 : 0)
addic rA, rB, -1
subfe rC, rA, rArC = (rB ? 0 : -1)
extsb rA, rA
srawi rB, rA, 0x1F
xor rC, rB, rA
subf rC, rC, rB
srawi rC, rC, 0x1FrC = (rA ? -1 : 0)
extsb rA, rA
xor rC, rA, rS
srawi rB, rC, 0x1F
xor rC, rB, rC
subf rC, rC, rB
srawi rC, rC, 0x1FrC = (rA == rS) ? 0 : -1
可以編寫(xiě)一個(gè)等價(jià)的程序測(cè)試一些不同的輸入值來(lái)驗(yàn)證。
RISC-V
寄存器
32 個(gè)定點(diǎn)數(shù)寄存器如下:
Register NumberName...
0zero它總是返回零,對(duì)其寫(xiě)入也沒(méi)有效果
1ra返回地址
2sp棧指針
3gp一個(gè)全局指針,可以用于訪問(wèn)一些全局變量。沒(méi)有特定的用法
4tp線程指針
5t0無(wú)需保存的臨時(shí)變量,也作替代 LR
6-7t1-t2無(wú)需保存的臨時(shí)變量
8s0/fp棧幀指針,也可作為需要在當(dāng)前函數(shù)返回之前,恢復(fù)其本來(lái)值的臨時(shí)變量
9s1需要在當(dāng)前函數(shù)返回之前,恢復(fù)其本來(lái)值的臨時(shí)變量
10-11a0-a1函數(shù)參數(shù),或作為返回值
12-17a2-a7函數(shù)參數(shù)
18-27s2-s11需要在當(dāng)前函數(shù)返回之前,恢復(fù)其本來(lái)值的臨時(shí)變量
28-31t3-t6無(wú)需保存的臨時(shí)變量
32 個(gè)浮點(diǎn)數(shù)寄存器如下:
RegisterName...
0-7ft0-7臨時(shí)變量
8-9fs0-1需要維護(hù)的變量
10-11fa0-1參數(shù)/返回值
12-17fa2-7參數(shù)
18-27fs2-11需要維護(hù)的變量
28-31ft8-11臨時(shí)變量
指令集
RISC-V 的指令集使用模塊化的方式進(jìn)行組織,基本指令集包括 RV32I、RV32E(Embedded,RV32I 的子集,僅支持 16 個(gè)通用整數(shù)寄存器)、RV64I、RV128I;必須實(shí)現(xiàn)基本指令集其中一種。
擴(kuò)展指令集包括:M(整數(shù)乘除法)、A(存儲(chǔ)器原子操作指令和 Load-Reserved/Store-Conditional 指令)、F(單精度浮點(diǎn)指令)、D(雙精度浮點(diǎn)指令)、G(通用,即 IMAFD 的組合)、C(壓縮指令,指令長(zhǎng)為 16 位)等等。
特權(quán)級(jí)有 4 種,0 為用戶應(yīng)用程序,縮寫(xiě)為 U;1 為管理員,縮寫(xiě)為 S,2 為 Hypervisor,縮寫(xiě)為 H;3 為機(jī)器,縮寫(xiě)為 M。一般情況下只需要使用 M 和 U。
RISC-V 架構(gòu)的一個(gè)特殊之處是對(duì)任何的運(yùn)算指令錯(cuò)誤(包括整數(shù)與浮點(diǎn)指令)均不產(chǎn)生異常,而是產(chǎn)生某個(gè)特殊的默認(rèn)值,同時(shí),設(shè)置某些狀態(tài)寄存器的狀態(tài)位。RISC-V 架構(gòu)推薦軟件通過(guò)其他方法來(lái)找到這些錯(cuò)誤。
基礎(chǔ)指令說(shuō)明
addi rd, rs1, imm[11:0]
slti rd, rs1, imm[11:0]Set Less Than Immediate 如果 rs1 的值小于立即數(shù)的值,則 rd 為 1,否則為 0
sltiu rd, rs1, imm[11:0]
andi rd, rs1, imm[11:0]
ori rd, rs1, imm[11:0]
xori, rs1, imm[11:0]
slli, rs1, imm[11:0]Shift Left Logic Immediate
srli, rs1, imm[11:0]
srai, rs1, imm[11:0]
lui rd, immLoad Upper Immediate 將 20 位立即數(shù)的值左移 12 位,低位補(bǔ) 0 并寫(xiě)入 rd
auipc rd, immAdd Upper Immediate to PC 將 20 位立即數(shù)的值左移 12 位,低位補(bǔ) 0 和 PC 相加后寫(xiě)入 rd
add rd, rs1, rs2若結(jié)果發(fā)生溢出,將溢出位舍棄(無(wú)進(jìn)位、借位標(biāo)志)
sub rd, rs1, rs2若結(jié)果發(fā)生溢出,將溢出位舍棄(無(wú)進(jìn)位、借位標(biāo)志)
slt rd, rs1, rs2
sltu rd, rs1, rs2
and rd, rs1, rs2
or rd, rs1, rs2
xor rd, rs1, rs2
sll rd, rs1, rs2
srl rd, rs1, rs2
sra rd, rs1, rs2
jal rd, labelJump And Link 將 20 位立即數(shù)視為有符號(hào)數(shù)并乘以 2 和 PC 相加,作為跳轉(zhuǎn)地址。并將當(dāng)前 PC+4 的值寫(xiě)入 rd
jalr rd, rs1, immJump And Link Register 將 20 位立即數(shù)視為有符號(hào)數(shù)并乘以 2 和 rs1 相加,作為跳轉(zhuǎn)地址。并將當(dāng)前 PC+4 的值寫(xiě)入 rd
beq rs1, rs2, label若 rs1 和 rs2 相等,將 12 位立即數(shù)視為有符號(hào)數(shù)并乘以 2 和 PC 相加,作為跳轉(zhuǎn)地址。
bne rs1, rs2, label
blt rs1, rs2, label
bltu rs1, rs2, label
bge rs1, rs2, label
bgeu rs1, rs2, label
lw/lh/lb rd, offset[11:0](rs1)從存儲(chǔ)器中讀出一個(gè) 16/8 位的有符號(hào)數(shù)寫(xiě)入 rd
lhu/lbu rd, offset[11:0](rs1)從存儲(chǔ)器中讀出一個(gè) 16/8 位的無(wú)符號(hào)數(shù)寫(xiě)入 rd
sw/sh/sb rs2, offset[11:0](rs1)將 rs2 的低 32/16/8 位寫(xiě)回存儲(chǔ)器
csrrw rd, csr, rs1將 CSR 寄存器的值寫(xiě)入 rd,將 rs1 的值寫(xiě)入 CSR 寄存器
csrrs rd, csr, rs1以 rs1 的各比特位為參考,將 CSR 寄存器的對(duì)應(yīng)比特位置 1
csrrc rd, csr, rs1以 rs1 的各比特位為參考,將 CSR 寄存器的對(duì)應(yīng)比特位清 0
csrrwi rd, csr, imm[4:0]將 CSR 寄存器的值寫(xiě)入 rd,將 5 位立即數(shù)高位補(bǔ) 0 后寫(xiě)入 CSR 寄存器
csrrsi rd, csr, imm[4:0]將 5 位立即數(shù)高位補(bǔ) 0 后的各比特位為參考,將 CSR 寄存器的對(duì)應(yīng)比特位置 1
csrrci rd, csr, imm[4:0]將 5 位立即數(shù)高位補(bǔ) 0 后的各比特位為參考,將 CSR 寄存器的對(duì)應(yīng)比特位清 0
ecall產(chǎn)生環(huán)境調(diào)用異常(Environment Exception),mepc 寄存器的值更新為該指令的地址
ebreak產(chǎn)生斷點(diǎn)異常(Breakpoint Exception),mepc 寄存器的值更新為該指令的地址
mret異常返回
wfi處理器進(jìn)入休眠狀態(tài),直到中斷發(fā)生。如果中斷被全局關(guān)閉(通過(guò) mstatus 寄存器的 MIE 域),則不進(jìn)入中斷異常服務(wù)程序,而是繼續(xù)向下執(zhí)行
mul rd, rs1, rs2將兩個(gè) 32 位數(shù)相乘(得到一個(gè) 64 位數(shù)),將結(jié)果的低 32 位寫(xiě)入 rd。由于兩個(gè) 32 位操作數(shù)不論是否有符號(hào),相乘所得的低 32 位結(jié)果一定是相同的,因此該指令不區(qū)分符號(hào)。
mulh rd, rs1, rs2將兩個(gè) 32 位有符號(hào)數(shù)相乘(得到一個(gè) 64 位數(shù)),將結(jié)果的高 32 位寫(xiě)入 rd
mulhu rd, rs1, rs2將兩個(gè) 32 位無(wú)符號(hào)數(shù)相乘(得到一個(gè) 64 位數(shù)),將結(jié)果的高 32 位寫(xiě)入 rd
mulhsu rd, rs1, rs2將 32 位有符號(hào)數(shù) rs1 和無(wú)符號(hào)數(shù) rs2 相乘(得到一個(gè) 64 位數(shù)),將結(jié)果的高 32 位寫(xiě)入 rd
div rd, rs1, rs2有符號(hào)數(shù)除法。注意:除以零并不會(huì)產(chǎn)生異常,而是得到 -1
divu rd, rs1, rs2無(wú)符號(hào)數(shù)除法。注意:除以零并不會(huì)產(chǎn)生異常,而是得到 2^32-1
rem rd, rs1, rs2將 rs1 和 rs2 的值當(dāng)作有符號(hào)數(shù)相除,將余數(shù)寫(xiě)入 rd。注意:除以零并不會(huì)產(chǎn)生異常,而是得到 rs1
remu rd, rs1, rs2將 rs1 和 rs2 的值當(dāng)作無(wú)符號(hào)數(shù)相除,將余數(shù)寫(xiě)入 rd。注意:除以零并不會(huì)產(chǎn)生異常,而是得到 rs1
注:屏障指令、原子指令、浮點(diǎn)指令從略
一部分 32 位指令編碼空間試探性地(tentatively)分配給了超過(guò) 32 位長(zhǎng)的指令,如下所示:
RISC-V 指令長(zhǎng)度編碼方案。目前只有 16 位和 32 位編碼方案已凍結(jié)。
偽指令基礎(chǔ)指令含義
la rd, symbol (non-PIC)auipc rd, delta[31 : 12] + delta[11]
addi rd, rd, delta[11:0]Load absolute address, where delta = symbol ? pc
la rd, symbol (PIC)auipc rd, delta[31 : 12] + delta[11]
l{w|d} rd, rd, delta[11:0]Load absolute address, where delta = GOT[symbol] ? pc
lla rd, symbolauipc rd, delta[31 : 12] + delta[11]
addi rd, rd, delta[11:0]Load local address, where delta = symbol ? pc
l{b|h|w|d} rd, symbolauipc rd, delta[31 : 12] + delta[11]
l{b|h|w|d} rd, delta[11:0](rd)Load global
s{b|h|w|d} rd, symbol, rtauipc rt, delta[31 : 12] + delta[11]
s{b|h|w|d} rd, delta[11:0](rt)Store global
fl{w|d} rd, symbol, rtauipc rt, delta[31 : 12] + delta[11]
fl{w|d} rd, delta[11:0](rt)Floating-point load global
fs{w|d} rd, symbol, rtauipc rt, delta[31 : 12] + delta[11]
fs{w|d} rd, delta[11:0](rt)Floating-point store global
基礎(chǔ)指令使用和 pc 相關(guān)的取址,因此鏈接器把符號(hào)與 pc 相減得到偏移量。鏈接器把偏移量的第 11 比特加到高 20 比特上,抵消低 12 比特的符號(hào)擴(kuò)展。
nopaddi x0, x0, 0No operation
li rd, immediateMyriad sequencesLoad immediate
mv rd, rsaddi rd, rs, 0Copy register
not rd, rsxori rd, rs, -1One’s complement
neg rd, rssub rd, x0, rsTwo’s complement
negw rd, rssubw rd, x0, rsTwo’s complement word
sext.w rd, rsaddiw rd, rs, 0Sign extend word
seqz rd, rssltiu rd, rs, 1Set if = zero
snez rd, rssltu rd, x0, rsSet if ?= zero
sltz rd, rsslt rd, rs, x0Set if < zero
sgtz rd, rsslt rd, x0, rsSet if > zero
fmv.s rd, rsfsgnj.s rd, rs, rsCopy single-precision register
fabs.s rd, rsfsgnjx.s rd, rs, rsSingle-precision absolute value
fneg.s rd, rsfsgnjn.s rd, rs, rsSingle-precision negate
fmv.d rd, rsfsgnj.d rd, rs, rsCopy double-precision register
fabs.d rd, rsfsgnjx.d rd, rs, rsDouble-precision absolute value
fneg.d rd, rsfsgnjn.d rd, rs, rsDouble-precision negate
beqz rs, offsetbeq rs, x0, offsetBranch if = zero
bnez rs, offsetbne rs, x0, offsetBranch if ?= zero
blez rs, offsetbge x0, rs, offsetBranch if ≤ zero
bgez rs, offsetbge rs, x0, offsetBranch if ≥ zero
bltz rs, offsetblt rs, x0, offsetBranch if < zero
bgtz rs, offsetblt x0, rs, offsetBranch if > zero
bgt rs, rt, offsetblt rt, rs, offsetBranch if >
ble rs, rt, offsetbge rt, rs, offsetBranch if ≤
bgtu rs, rt, offsetbltu rt, rs, offsetBranch if >, unsigned
bleu rs, rt, offsetbgeu rt, rs, offsetBranch if ≤, unsigned
控制和狀態(tài)寄存器 CSR 需要通過(guò) CSRRW、CSRRS、CSRRC、CSRRWI、CSRRSI 以及 CSRRCI 指令訪問(wèn)。
偽指令基礎(chǔ)指令含義
j offsetjal x0, offsetJump
jal offsetjal x1, offsetJump and link
jr rsjalr x0, 0(rs)Jump register
jalr rsjalr x1, 0(rs)Jump and link register
retjalr x0, 0(x1)Return from subroutine
call offsetauipc x1, offset[31 : 12] + offset[11] jalr x1, offset[11:0](x1)Call far-away subroutine
tail offsetauipc x6, offset[31 : 12] + offset[11] jalr x0, offset[11:0](x6)Tail call far-away subroutine
fencefence iorw, iorwFence on all memory and I/O
rdinstret[h] rdcsrrs rd, instret[h], x0Read instructions-retired counter
rdcycle[h] rdcsrrs rd, cycle[h], x0Read cycle counter
rdtime[h] rdcsrrs rd, time[h], x0Read real-time clock
csrr rd, csrcsrrs rd, csr, x0Read CSR
csrw csr, rscsrrw x0, csr, rsWrite CSR
csrs csr, rscsrrs x0, csr, rsSet bits in CSR
csrc csr, rscsrrc x0, csr, rsClear bits in CSR
csrwi csr, immcsrrwi x0, csr, immWrite CSR, immediate
csrsi csr, immcsrrsi x0, csr, immSet bits in CSR, immediate
csrci csr, immcsrrci x0, csr, immClear bits in CSR, immediate
frcsr rdcsrrs rd, fcsr, x0Read FP control/status register
fscsr rd, rscsrrw rd, fcsr, rsSwap FP control/status register
fscsr rscsrrw x0, fcsr, rsWrite FP control/status register
frrm rdcsrrs rd, frm, x0Read FP rounding mode
fsrm rd, rscsrrw rd, frm, rsSwap FP rounding mode
fsrm rscsrrw x0, frm, rsWrite FP rounding mode
frflags rdcsrrs rd, fflags, x0Read FP exception flags
fsflags rd, rscsrrw rd, fflags, rsSwap FP exception flags
fsflags rscsrrw x0, fflags, rsWrite FP exception flags
異常
同步異常指試圖執(zhí)行指令而造成的異常,例如非法指令異常。
異步異常指不能精確定位到某條指令的異常,例如外部中斷是一種精確異步異常,而訪存出錯(cuò)是一種非精確異步異常。
當(dāng)發(fā)生異常時(shí),處理器跳轉(zhuǎn)到由 mtvec 寄存器指定的地址處執(zhí)行。此外處理器還會(huì)更新如下寄存器:
mcause:保存了產(chǎn)生異常的原因,最高位為 1 表示中斷,否則為異常(調(diào)試斷點(diǎn)是一種異常)。
mtval(或 mbadaddr):如果是訪存異常,存儲(chǔ)了產(chǎn)生異常的存儲(chǔ)器地址;如果是指令異常,存儲(chǔ)了產(chǎn)生異常的指令編碼。
mstatus:設(shè)置 MIE 域、MPIE 域和 MPP 域。相當(dāng)于關(guān)閉全局中斷。
mepc:存儲(chǔ)了異常返回地址。對(duì)于中斷,mepc 為下一條指令地址;對(duì)于異常,mepc 為當(dāng)前指令地址。
mtvec 的低 2 位為 MODE 域,其余為 BASE 域。若為 0 則所有異常均跳轉(zhuǎn)到 BASE 地址;若為 1 則跳轉(zhuǎn)到 BASE+4*CAUSE 地址,CAUSE 表示異常編號(hào)。
退出異常使用 mret 指令,從 mepc 寄存器指定處繼續(xù)執(zhí)行并更新 mstatus 寄存器,相當(dāng)于重新打開(kāi)全局中斷。由于 RISC-V 架構(gòu)規(guī)定的進(jìn)入異常和退出異常機(jī)制中沒(méi)有硬件自動(dòng)保存和恢復(fù)上下文的操作,因此需要通過(guò)軟件來(lái)保存和恢復(fù)上下文。RISC-V 架構(gòu)默認(rèn)不支持中斷嵌套,開(kāi)發(fā)者可以在中斷服務(wù)程序中通過(guò)修改 mstatus 的 MIE 域重新使能全局中斷,同時(shí)維護(hù) mepc 寄存器及上下文的恢復(fù)與保存。
RISC-V 的中斷分為四種,由 mie 寄存器負(fù)責(zé)使能,由 mip 寄存器反映中斷等待(pending)狀態(tài) :
外部中斷由 PLIC(Platform Level Interrupt Controller,平臺(tái)級(jí)中斷控制器)進(jìn)行仲裁和派發(fā)。包括優(yōu)先級(jí)和使能控制等。
計(jì)時(shí)器中斷由 CLINT(Core Local Interrupt Controller,核局部中斷控制器)管理,主要是設(shè)置 mtime 和 mtimecmp 寄存器。
軟件中斷由 msip 寄存器觸發(fā),對(duì)其寫(xiě) 1 或 0 即可觸發(fā)或清除軟件中斷。
調(diào)試中斷。
外部中斷的優(yōu)先級(jí)高于軟件中斷,軟件中斷的優(yōu)先級(jí)高于計(jì)時(shí)器中斷。
引用
總結(jié)
以上是生活随笔為你收集整理的i基准指令集 mips_ARM/MIPS/PowerPC/RISC-V 指令集快速入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: EMC存储常用命令
- 下一篇: lcd屏幕有mipi接口吗_LCD屏幕M