i基准指令集 mips_ARM/MIPS/PowerPC/RISC-V 指令集快速入门
這里所介紹的指令集架構均屬于 RISC,相比 CISC 更簡單。但是 ARM 比較特殊,因為它作為一個 RISC 架構竟然有 push/pop 指令……
ARMv7
ARM 指令集從舊到新有 ARMv6、ARMv7、ARMv7s、ARMv8,使用新指令集的芯片也能支持舊的指令集,但是無法發揮出較好的性能。同時要注意,指令集版本不同的靜態庫是不能一起使用的。
ARM 有兩種工作狀態,ARM 狀態的指令長度是 32 位的,Thumb 狀態的指令長度是 16 位的(從 ARMv6-T2 開始引入的 Thumb-2 指令集也支持 32 位的指令,具有 .w 后綴)
使用 Thumb 指令集可以得到較小的二進制文件,但是可以訪問的寄存器更少,產生的指令數量更多,性能會有損失。
寄存器
Register...
r0函數返回值或函數參數
r1~r3函數參數,更多參數使用棧傳遞
r4~r10臨時變量
r11函數棧幀?FP(類似于?EBP?寄存器)
r12內部過程調用寄存器?IP
r13棧指針?SP
r14鏈接寄存器?LR,用于存儲將要跳轉到的地址
r15程序計數器?PC
Cortex-M 含有兩個棧指針寄存器(SP),分別為 PSP(Process SP)和 MSP(Main SP)。
ARM 指令
指令結構為 MNEMONIC{S}{cond} {Rd}, Operand1, Operand2
如果指令后加了 S,將依據計算結果更新當前程序狀態寄存器 CPSR 中相應的標志。
cond 表示執行條件,見下表。
擴展助記符意義(整形)意義(浮點)條件
EQ相等相等Z==1
NE不相等不相等或無序(即至少有一個 NaN)Z==0
CS/HS進位置位/無符號高于等于大于等于或無序C==1
CC/LO進位復位/無符號低于小于C==0
MI減法、負數小于N==1
PL加法、非負數大于等于,或無序N==0
VS溢出置位無序V==1
VC溢出復位不無序V==0
HI無符號高于大于或無序C==1 且 Z==0
LS無符號不高于小于或相等C==0 或 Z==1
GE有符號大于等于大于等于N==V
LT有符號小于小于或無序N!=V
GT有符號大于大于Z==0 且 N==V
LE有符號小于等于小于等于或無序Z==1 或 N!=V
AL(default)無條件無條件
第三個操作數可以是寄存器,也可以是要進行的移位操作。可能的操作有 LSL/LSR/ASR/ROR/RRX,其中 RRX 表示右移一位,最高位由 APSR 寄存器的狀態位 C 填充,移出的位給狀態位 C。
Mnemonic...
mov復制寄存器。例如 MOV R0,R2,LSL #3 表示把 R2 左移 3 位后傳給 R0。
lsl/lsr/asr/ror邏輯左移,邏輯右移,算數右移,循環右移
push把立即數、單個寄存器,多個寄存器壓棧。多個寄存器按從右到左壓棧
pop出棧到單個寄存器或多個寄存器(從左到右的順序)
ldr/strldr 從內存中讀 32 位數據,str 寫 32 位數據到內存。如 ldr r1, [r2, #0x10] 即 r1 = *(r2+0x10);str r1, [r2, #0x01] 即 *(r2+1)=r1。相應地,讀寫 16 位時 ldrh/strh;8 位時 ldrb/strb。例如 ldrneh 即不相等時讀半字。
swp交換值,可用于實現信號量
b/blb 跳轉,bl 跳轉并把下一條指令地址存儲到 lr
bx/blx Rm跳轉并切換狀態。由于指令是 2 或 4 字節對齊的,地址的最低位一定是 0,故若?Rm & 0x01==1?則令 CPSR.T=1,把目標地址解釋為 Thumb 代碼;否則令?CPSR.T=0,目標地址解釋為 ARM 代碼
add/sub加減法,更新標志位
sbc帶借位減法,Rd = ~Ra + Rb + CPSR.C
cmp比較兩個寄存器或一個立即數(使用減法)并更新標志位
tst/teq測試相等
mul/mla/umullmul 乘法,mla 乘加,即 Ra*Rb+Rc,umull 64 位乘法
svc/swi系統調用
and/orr/eor按位與,按位或,按位異或
幾個 SIMD 指令:
Mnemonic...
ldmib/stmib/ldmdb/stmdbb 表示存儲器指針在保存/讀取第一個值之前更新;i 表示更新方式為增加,d 表示更新方式為減少
ldmfa/stmfa/ldmfd/stmfd存儲器指針為 SP 時,就等價于該指令。f 表示堆棧指針指向內含有效數據項的最高地址;a 表示堆棧往高地址增長,d 表示堆棧往低地址增長
ldmea/stmea/ldmed/stmede 表示堆棧指針指向堆棧的第一個空位置 ;a 表示堆棧往高地址增長,d 表示堆棧往低地址增長。
協處理器指令格式:
MRC/MCR {cond} coproc,opcode1,Rd,CRn,CRm{,opcode2}
MCR:從寄存器到協處理器
MRC:從協處理器到寄存器
coproc:協處理器名稱,p0~p15
MSR:從寄存器到狀態寄存器,如 MSR CPSR,R0
MRS:從狀態寄存器到寄存器,如 MRS R2,SPSR
中斷
Cortex-A 處理器發生中斷時,先跳轉進 IRQ 入口,再通過軟件判斷是由哪個中斷源觸發,獲得相對應的中斷服務程序(ISR)的地址。而 Cortex-M 處理器發生中斷時,CPU 自動從中斷向量表中尋找相應的中斷服務程序并跳轉。
鏈接寄存器(LR)的數值會被更新為 EXC_RETURN 值(詳細含義可自行搜索)。然后硬件自動將 r0, r1, r2, r3, r12, lr, pc, psr 寄存器依次入棧,同時更新 psp 寄存器。中斷處理函數結束時,通過 bx lr 指令觸發中斷返回,處理器將自動保存的寄存器值從棧上彈出并恢復給相應的寄存器。
svc 指令用于系統調用,如 svc #0x900004 調用 sys_write
另一種方法是把編號傳給 r7(如 4 為 sys_write),再使用 swi 0 進行調用。
MIPS32
寄存器
Register NumberName...
0zero它總是返回零,對其寫入也沒有效果
1at匯編器臨時寄存器,用于加載 16 位以上的大常數使用
2-3v0,v1函數返回值,對于 64 位的返回值,兩個寄存器都要用到
4-7a0-a3函數調用參數,更多參數使用棧傳遞
8-15t0-t7無需保存的臨時變量
16-23s0-s7需要在當前函數返回之前,恢復其本來值的臨時變量
24,25t8-t9無需保存的臨時變量
26k0發生中斷時,在中斷處理過程中用作臨時變量
27k1用于中斷嵌套的深度計數器。也可作為臨時變量
28gp一個全局指針,可以用于訪問一些全局變量。沒有特定的用法
29sp棧指針
30s8/fp棧幀指針,也可作為需要維護值的臨時變量
31ra保存了函數的返回地址,類似于?lr
此外還有不可直接操作的 lo、hi 寄存器,在運算指令中會用到。
指令
Mnemonic...
lb/lh/lw從存儲器中讀取一個 byte/half word/word 的有符號數到寄存器中。lb r1, 0(r2) 即 r1=(signed int)*(char*)(r2+0)
lbu/lhu從存儲器中讀取一個 byte/half word 的無符號數到寄存器中。lhu r1, 0(r2) 即 r1=(unsigned int)*(short*)(r2+0)
sb/sh/sw把一個 byte/half word/word 的數據從寄存器存儲到存儲器中。如 sb r1, 0(r2) 即 *(char*)(r2+0)=(char)r1
llo/lhi加載低半字/加載高半字,lhi r1,2 即把 r1 的高半字設為 2
lui把一個 16 位的立即數填入到寄存器的高 16 位,低 16 位補零。i 表示立即數
mflo/mfhi/mtlo/mthi讀寫 lo、hi 寄存器,mflo r1 即 r1=lo,mthi r1 即 hi=r1
add/addu把兩個定點寄存器的內容相加 add r1,r2,r3 即r1=r2+r3;u 為不帶符號加
addi/addiu把一個寄存器的內容加上一個立即數 add r1,r2,#3 即 r1=r2+3;u 為不帶符號加
sub/subu把兩個定點寄存器的內容相減 sub r1,r2,r3 即 r1=r2-r3
div/divu兩個定點寄存器的內容相除 div r1,r2 即 lo=r1/r2; hi=r1%r2
mult/multu兩個定點寄存器的內容相乘 mult r1,r2 即 hi:lo=r1*r2
and/andi與運算,兩個寄存器中的內容相與 and r1,r2,r3 即 r1=r2&r3
or/ori或運算,or r1,r2,r3 即 r1=r2|r3
nor或非運算,nor r1,r2,r3 即 r1=~(r2|r3)
xor/xori異或運算,xor r1,r2,r3 即 r1=r2^r3
beq/beqz/bnez/bne條件轉移,eq 相等,z 零,ne 不等。beq r1,r2,label 即 r1 等于 r2 時跳轉。bnez r1,label 即 r1 非 0 時跳轉
bgtz/blez條件轉移,gt 大于,le 小于等于
j/jr/jal/jalrj 相對跳轉,jr 使用寄存器絕對跳轉,jal 把下一條指令地址給 ra 并相對跳轉,jalr 把下一條指令地址給 ra 并使用寄存器絕對跳轉
sll/sllv邏輯左移 sll r1,r2,#2,即 r1=r2<<2
sra/srav算數右移 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,那么設置 r1 的值為 1,否則設置 r1 的值為 0
mov/movz/movn復制寄存器 mov r1,r2;movz r1,r2,r3 即 r3 為零則復制 r2 到 r1;movn 即 r3 為負時復制
nop空指令
trap根據地址向量轉入管態
eret/rfe從異常中返回到用戶態
syscall把系統調用號傳給 v0,把參數傳給 a0~a3,然后使用 syscall 進入內核態
MIPS 有一個特色:分支延遲槽(branch delay slot)。它的意思是,當遇到分支指令時(即 j/jr/jal/jalr),該分支指令的下一條指令一定會被執行。因此 jal 和 jalr 所設置的 ra 寄存器的值,實際上是分支指令所在地址 +8,而非 +4。這一點在調試的時候需要尤其注意。
此外,在 DIV、DIVU、MULT、MULTU 指令之后,在新的結果寫入 HI 或 LO 之前,必須先用 MFHI 、MFLO 將 HI、LO 讀出。否則兩次連續對 HI、LO 的寫入會導致下次讀取時產生不可預料的值。
中斷
發生中斷時,處理器把引發異常的指令地址傳給 CR0 中的 EPC 寄存器,把 pc 的值設置為 0x8000 0180,把異常原因傳給 CR0 中的 Cause 寄存器。然后在異常處理程序中使用 mfepc 指令(等價于 mfc0 R, EPC)將 EPC 的值賦給 k0;使用 mfco 指令把異常原因讀出(等價于 mfc0 R, Cause)。而且在使用這兩個指令時,需要多加一個 nop 指令以等待其完成。
對于 MIPS I 和 MIPS II 處理器,從異常返回時,要到 EPC 所指向的地址處繼續執行,并使用 rfe 指令切換回用戶態(SR 寄存器),匯編指令為:
mfc0 k0, epc
jr k0
rfe
這里 jr 和 rfe 是一起執行的。而在 MIPS III 中只需要一條 eret 指令就可以了。
修改 CR0 使用 mtc0 指令,注意 CR0 只能在內核態下訪問。
浮點數
使用 lwc1 把一個 32 位字從存儲器加載到 CR1,然后可以進行運算:add.s、add.d、sub.s、sub.d、mul.s、mul.d、div.s、div.d。其中 s 表示單精度,d 表示雙精度。最后使用 swc1 把一個 32 位字從 CR1 保存到存儲器。
PowerPC 405
寄存器
通用寄存器 r0~r31:
r1 用作棧指針 sp,r3 用作返回值。
函數參數從左往右依次使用 r3,r4,r5,r6…傳遞,也可以用棧傳遞。
函數內部臨時變量依次使用 r31,r30,r29,r28…,而且函數需要維護 r3~r31 原本的值,在函數返回時恢復到進入時的狀態。
定點數異常寄存器(Fixed-Point Exception Register,XER)反映算術操作的溢出 XER[OV]、進位 XER[CA] 和總溢出(Summary Overflow)XER[SO]。
條件寄存器 CR 在一些條件轉移指令時會用到。它分為 8 個 4bit 組,依次為 CR0~CR7,其比特位含義如下:
0 1 2 3
| LT | GT | EQ | SO |
指令集
Mnemonic...
addi rD, rA, SIMM先把 SIMM 進行符號擴展到 32 位,如果 rA 為 r0 則直接傳給 rD,否則加上 rA 的值傳給 rD
addis rD, rA, SIMM把 SIMM 低位補 16 個 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 寄存器,實際上是 mfspr 指令的別名
b/ba/bctr/blr/bl/bctrl/blrl無條件跳轉,a 表示無條件跳轉,ctr 表示跳轉到 CTR 寄存器指定的位置,lr 表示跳轉到 LR 寄存器指定的位置;再加 l 表示并把下一條指令的地址 賦給 lr
blt/ble/beq/bge/bgt/bne條件跳轉。這些指令助記符后同樣可以加 a、lr、ctr 并再加 l。如 beqctrl 表示相等則跳轉到 ctr 處并更新 lr
cmpw/cmpwi/cmplw/cmplwi比較字 w 或邏輯字 lw,并更新特定的 CR 域(默認 CR0)
sraw/srawi算數右移
srw/srwi/slw/slwi邏輯右移、邏輯左移
注意上表的 SIMM 是帶符號地從 16 位擴展到 32 位,例如 00AE0000+(signed short)AAD0 得到 00ADAAD0(舍去進位的 1)。
64 位整數的加減法對應如下指令:
addc r8,r6,r4 # 低位字相加,記錄進位 XER[CA]
adde r7,r5,r3 # 高位字相加,使用前面的進位
---
subfc r8,r6,r4 # 減去低位字,記錄借位 XER[CA]
subfe r7,r5,r3 # 減去高位字,使用前面的借位
最終效果就是 (r7:r8)=(r3:r4)±(r5:r6)。
CR0~CR7 都可用于反映指令的結果。定點數運算指令如 addic.、andi.、andis. 后面的小數點 . 表示它會更新 CR0 反映他們的結果,如果沒有這個點,則只會更新 XER。更新方式為,把結果與 0 進行比較,更新 CR0 的高 3bit,然后把 XER 的 SO 位復制到 CR0 的 SO 位。此外 CR1 還可用作浮點操作的結果(PPC 405 不支持)。
函數調用約定
…調用方傳參,參數放到 r3
bl func跳轉到 func,把下一條指令地址放到lr寄存器
stwu r1, -0xF8(r1)相當于 *(sp-F8h)=sp,然后 sp-=F8h。這個減去的值叫做 back_chain
mflr r0把 lr 寄存器賦給 r0
stw r31, 0xF8-4(r1)把進入時的寄存器值備份到棧上
stw r0, 0xF8+4(r1)把返回地址保存到棧上,方便后續用 bl 調用別的函數
根據以上過程,可以得出此時棧的情況(上面是低地址,下面是高地址)
地址保存的值
sp棧基地址,進入時的 sp,其實就是 sp+F8h
sp+4分析一下可以發現,如果該函數再調用別的函數,那么LR 存到這里
sp+8局部變量。有時也作為棧傳遞的參數
……
sp+F8h-8備份進入時的 r30
sp+F8h-4備份進入時的 r31
sp+F8h分析一下可以發現,應當是調用者的棧基地址,即sp+F8h+??
sp+F8h+4返回地址*
函數返回過程如下:
lwz r0, F8h+4(r1)把棧上的返回地址讀到 r0
mtlr r0把 r0 賦給 lr
lwz r31, F8h-4(r1)把進入時備份的值恢復給 r31
……
addi r1, r1, F8h恢復堆棧指針
blrjmp lr
Snippet
下面給出一些匯編指令的化簡結果,具體細節可以參考指令手冊。
匯編指令對應的 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
可以編寫一個等價的程序測試一些不同的輸入值來驗證。
RISC-V
寄存器
32 個定點數寄存器如下:
Register NumberName...
0zero它總是返回零,對其寫入也沒有效果
1ra返回地址
2sp棧指針
3gp一個全局指針,可以用于訪問一些全局變量。沒有特定的用法
4tp線程指針
5t0無需保存的臨時變量,也作替代 LR
6-7t1-t2無需保存的臨時變量
8s0/fp棧幀指針,也可作為需要在當前函數返回之前,恢復其本來值的臨時變量
9s1需要在當前函數返回之前,恢復其本來值的臨時變量
10-11a0-a1函數參數,或作為返回值
12-17a2-a7函數參數
18-27s2-s11需要在當前函數返回之前,恢復其本來值的臨時變量
28-31t3-t6無需保存的臨時變量
32 個浮點數寄存器如下:
RegisterName...
0-7ft0-7臨時變量
8-9fs0-1需要維護的變量
10-11fa0-1參數/返回值
12-17fa2-7參數
18-27fs2-11需要維護的變量
28-31ft8-11臨時變量
指令集
RISC-V 的指令集使用模塊化的方式進行組織,基本指令集包括 RV32I、RV32E(Embedded,RV32I 的子集,僅支持 16 個通用整數寄存器)、RV64I、RV128I;必須實現基本指令集其中一種。
擴展指令集包括:M(整數乘除法)、A(存儲器原子操作指令和 Load-Reserved/Store-Conditional 指令)、F(單精度浮點指令)、D(雙精度浮點指令)、G(通用,即 IMAFD 的組合)、C(壓縮指令,指令長為 16 位)等等。
特權級有 4 種,0 為用戶應用程序,縮寫為 U;1 為管理員,縮寫為 S,2 為 Hypervisor,縮寫為 H;3 為機器,縮寫為 M。一般情況下只需要使用 M 和 U。
RISC-V 架構的一個特殊之處是對任何的運算指令錯誤(包括整數與浮點指令)均不產生異常,而是產生某個特殊的默認值,同時,設置某些狀態寄存器的狀態位。RISC-V 架構推薦軟件通過其他方法來找到這些錯誤。
基礎指令說明
addi rd, rs1, imm[11:0]
slti rd, rs1, imm[11:0]Set Less Than Immediate 如果 rs1 的值小于立即數的值,則 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 位立即數的值左移 12 位,低位補 0 并寫入 rd
auipc rd, immAdd Upper Immediate to PC 將 20 位立即數的值左移 12 位,低位補 0 和 PC 相加后寫入 rd
add rd, rs1, rs2若結果發生溢出,將溢出位舍棄(無進位、借位標志)
sub rd, rs1, rs2若結果發生溢出,將溢出位舍棄(無進位、借位標志)
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 位立即數視為有符號數并乘以 2 和 PC 相加,作為跳轉地址。并將當前 PC+4 的值寫入 rd
jalr rd, rs1, immJump And Link Register 將 20 位立即數視為有符號數并乘以 2 和 rs1 相加,作為跳轉地址。并將當前 PC+4 的值寫入 rd
beq rs1, rs2, label若 rs1 和 rs2 相等,將 12 位立即數視為有符號數并乘以 2 和 PC 相加,作為跳轉地址。
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)從存儲器中讀出一個 16/8 位的有符號數寫入 rd
lhu/lbu rd, offset[11:0](rs1)從存儲器中讀出一個 16/8 位的無符號數寫入 rd
sw/sh/sb rs2, offset[11:0](rs1)將 rs2 的低 32/16/8 位寫回存儲器
csrrw rd, csr, rs1將 CSR 寄存器的值寫入 rd,將 rs1 的值寫入 CSR 寄存器
csrrs rd, csr, rs1以 rs1 的各比特位為參考,將 CSR 寄存器的對應比特位置 1
csrrc rd, csr, rs1以 rs1 的各比特位為參考,將 CSR 寄存器的對應比特位清 0
csrrwi rd, csr, imm[4:0]將 CSR 寄存器的值寫入 rd,將 5 位立即數高位補 0 后寫入 CSR 寄存器
csrrsi rd, csr, imm[4:0]將 5 位立即數高位補 0 后的各比特位為參考,將 CSR 寄存器的對應比特位置 1
csrrci rd, csr, imm[4:0]將 5 位立即數高位補 0 后的各比特位為參考,將 CSR 寄存器的對應比特位清 0
ecall產生環境調用異常(Environment Exception),mepc 寄存器的值更新為該指令的地址
ebreak產生斷點異常(Breakpoint Exception),mepc 寄存器的值更新為該指令的地址
mret異常返回
wfi處理器進入休眠狀態,直到中斷發生。如果中斷被全局關閉(通過 mstatus 寄存器的 MIE 域),則不進入中斷異常服務程序,而是繼續向下執行
mul rd, rs1, rs2將兩個 32 位數相乘(得到一個 64 位數),將結果的低 32 位寫入 rd。由于兩個 32 位操作數不論是否有符號,相乘所得的低 32 位結果一定是相同的,因此該指令不區分符號。
mulh rd, rs1, rs2將兩個 32 位有符號數相乘(得到一個 64 位數),將結果的高 32 位寫入 rd
mulhu rd, rs1, rs2將兩個 32 位無符號數相乘(得到一個 64 位數),將結果的高 32 位寫入 rd
mulhsu rd, rs1, rs2將 32 位有符號數 rs1 和無符號數 rs2 相乘(得到一個 64 位數),將結果的高 32 位寫入 rd
div rd, rs1, rs2有符號數除法。注意:除以零并不會產生異常,而是得到 -1
divu rd, rs1, rs2無符號數除法。注意:除以零并不會產生異常,而是得到 2^32-1
rem rd, rs1, rs2將 rs1 和 rs2 的值當作有符號數相除,將余數寫入 rd。注意:除以零并不會產生異常,而是得到 rs1
remu rd, rs1, rs2將 rs1 和 rs2 的值當作無符號數相除,將余數寫入 rd。注意:除以零并不會產生異常,而是得到 rs1
注:屏障指令、原子指令、浮點指令從略
一部分 32 位指令編碼空間試探性地(tentatively)分配給了超過 32 位長的指令,如下所示:
RISC-V 指令長度編碼方案。目前只有 16 位和 32 位編碼方案已凍結。
偽指令基礎指令含義
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
基礎指令使用和 pc 相關的取址,因此鏈接器把符號與 pc 相減得到偏移量。鏈接器把偏移量的第 11 比特加到高 20 比特上,抵消低 12 比特的符號擴展。
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
控制和狀態寄存器 CSR 需要通過 CSRRW、CSRRS、CSRRC、CSRRWI、CSRRSI 以及 CSRRCI 指令訪問。
偽指令基礎指令含義
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
異常
同步異常指試圖執行指令而造成的異常,例如非法指令異常。
異步異常指不能精確定位到某條指令的異常,例如外部中斷是一種精確異步異常,而訪存出錯是一種非精確異步異常。
當發生異常時,處理器跳轉到由 mtvec 寄存器指定的地址處執行。此外處理器還會更新如下寄存器:
mcause:保存了產生異常的原因,最高位為 1 表示中斷,否則為異常(調試斷點是一種異常)。
mtval(或 mbadaddr):如果是訪存異常,存儲了產生異常的存儲器地址;如果是指令異常,存儲了產生異常的指令編碼。
mstatus:設置 MIE 域、MPIE 域和 MPP 域。相當于關閉全局中斷。
mepc:存儲了異常返回地址。對于中斷,mepc 為下一條指令地址;對于異常,mepc 為當前指令地址。
mtvec 的低 2 位為 MODE 域,其余為 BASE 域。若為 0 則所有異常均跳轉到 BASE 地址;若為 1 則跳轉到 BASE+4*CAUSE 地址,CAUSE 表示異常編號。
退出異常使用 mret 指令,從 mepc 寄存器指定處繼續執行并更新 mstatus 寄存器,相當于重新打開全局中斷。由于 RISC-V 架構規定的進入異常和退出異常機制中沒有硬件自動保存和恢復上下文的操作,因此需要通過軟件來保存和恢復上下文。RISC-V 架構默認不支持中斷嵌套,開發者可以在中斷服務程序中通過修改 mstatus 的 MIE 域重新使能全局中斷,同時維護 mepc 寄存器及上下文的恢復與保存。
RISC-V 的中斷分為四種,由 mie 寄存器負責使能,由 mip 寄存器反映中斷等待(pending)狀態 :
外部中斷由 PLIC(Platform Level Interrupt Controller,平臺級中斷控制器)進行仲裁和派發。包括優先級和使能控制等。
計時器中斷由 CLINT(Core Local Interrupt Controller,核局部中斷控制器)管理,主要是設置 mtime 和 mtimecmp 寄存器。
軟件中斷由 msip 寄存器觸發,對其寫 1 或 0 即可觸發或清除軟件中斷。
調試中斷。
外部中斷的優先級高于軟件中斷,軟件中斷的優先級高于計時器中斷。
引用
總結
以上是生活随笔為你收集整理的i基准指令集 mips_ARM/MIPS/PowerPC/RISC-V 指令集快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EMC存储常用命令
- 下一篇: lcd屏幕有mipi接口吗_LCD屏幕M