第1章 ARMv8簡介
1.1基礎認識
ARMv8的架構繼承以往ARMv7與之前處理器技術的基礎,除了現有的16/32bit的Thumb2指令支持外,也向前兼容現有的A32(ARM 32bit)指令集,基於64bit的AArch64架構,除了新增A64(ARM 64bit)指令集外,也擴充了現有的A32(ARM 32bit)和T32(Thumb2 32bit)指令集,另外還新增加了CRYPTO(加密)模塊支持。
1.2 相關專業名詞解釋
| AArch32 |
描述32bit Execution State |
| AArch64 |
描述64bit Execution State |
| A32、T32 |
AArch32 ISA (Instruction Architecture) |
| A64 |
AArch64 ISA (Instruction Architecture) |
| Interprocessing |
描述AArch32和AArch64兩種執行狀態之間的切換 |
| SIMD |
Single-Instruction, Multiple-Data (單指令多數據) |
(參考文檔:ARMv8-A Architecture reference manual-DDI0487A_g_armv8_arm.pdf)
第2章 Execution State
2.1 提供兩種Execution State
• ARMv8 提供AArch32 state和 AArch64 state 兩種Execution State,下面是兩種Execution State對比.
| Execution State |
Note |
|
AArch32 |
提供13個32bit通用寄存器R0-R12,一個32bit PC指針 (R15)、堆棧指針SP (R13)、鏈接寄存器LR (R14) |
| 提供一個32bit異常鏈接寄存器ELR, 用於Hyp mode下的異常返回 |
|
| 提供32個64bit SIMD向量和標量floating-point支持 |
|
| 提供兩個指令集A32(32bit)、T32(16/32bit) |
|
| 兼容ARMv7的異常模型 |
|
| 協處理器只支持CP10\CP11\CP14\CP15 |
|
|
AArch64 |
提供31個64bit通用寄存器X0-X30(W0-W30),其中X30是程序鏈接寄存器LR |
| 提供一個64bit PC指針、堆棧指針SPx 、異常鏈接寄存器ELRx |
|
| 提供32個128bit SIMD向量和標量floating-point支持 |
|
| 定義ARMv8異常等級ELx(x<4),x越大等級越高,權限越大 |
|
| 定義一組PE state寄存器PSTATE(NZCV/DAIF/CurrentEL/SPSel等),用於保存PE當前的狀態信息 |
|
| 沒有協處理器概念 |
2.2 決定Execution State的條件
| SPSR_EL1.M[4] 決定EL0的執行狀態,為0 =>64bit ,否則=>32bit |
| HCR_EL2.RW 決定EL1的執行狀態,為1 =>64bit ,否則=>32bit |
| SCR_EL3.RW確定EL2 or EL1的執行狀態,為1 =>64bit ,否則=>32bit |
| AArch32和AArch64之間的切換只能通過發生異常或者系統Reset來實現.(A32 -> T32之間是通過BX指令切換的) |

第3章 Exception Level
• ARMv8定義EL0-EL3共 4個Exception Level來控制PE的行為.
| ELx(x<4),x越大等級越高,執行特權越高 |
| 執行在EL0稱為非特權執行 |
| EL2 沒有Secure state,只有Non-secure state |
| EL3 只有Secure state,實現EL0/EL1的Secure 和Non-secure之間的切換 |
| EL0 & EL1 必須要實現,EL2/EL3則是可選實現 |
3.1 Exception Level 與Security
| Exception Level |
|
| EL0 |
Application |
| EL1 |
Linux kernel- OS |
| EL2 |
Hypervisor (可以理解為上面跑多個虛擬OS) |
| EL3 |
Secure Monitor(ARM Trusted Firmware) |
| Security |
|
| Non-secure |
EL0/EL1/EL2, 只能訪問Non-secure memory |
| Secure |
EL0/EL1/EL3, 可以訪問Non-secure memory & Secure memory,可起到物理屏障安全隔離作用 |
3.1.1 EL3使用AArch64、AArch32的對比
|
|
Note |
|
Common |
User mode 只執行在Non- Secure EL0 or Secure ELO |
| SCR_EL3.NS決定的是low level EL的secure/non-secure狀態,不是絕對自身的 |
|
| EL2只有Non-secure state |
|
| EL0 既有Non-secure state 也有Secure state |
|
|
EL3 AArch64 |
若EL1使用AArch32,那么Non- Secure {SYS/FIQ/IRQ/SVC/ABORT/UND} 模式執行在Non-secure EL1,Secure {SYS/FIQ/IRQ/SVC/ABORT/UND}模式執行在Secure EL1 |
| 若 SCR_EL3.NS == 0,則切換到Secure EL0/EL1狀態,否則切換到Non-secure ELO/EL1狀態 |
|
| Secure state 只有Secure EL0/EL1/EL3 |
|
|
EL3 AArch32 |
User mode 只執行在Non- Secure EL0 or Secure ELO |
| 若EL1使用AArch32,那么Non- Secure {SYS/FIQ/IRQ/SVC/ABORT/UND} 模式執行在Non-secure EL1,Secure {SYS/FIQ/IRQ/SVC/ABORT/UND}模式執行在EL3 |
|
| Secure state只有Secure EL0/EL3,沒有Secure EL1,要注意和上面的情況不同 |
• 當EL3使用AArch64時,有如下結構組合:

• 當EL3使用AArch32時,有如下結構組合:

3.2 ELx 和 Execution State 組合
•假設EL0-EL3都已經實現,那么將會有如下組合
| 五類組合 |
|
| EL0/EL1/EL2/EL3 => AArch64 |
此兩類組合不存在64bit –> 32bit之間的所謂 Interprocessing 切換 |
| EL0/EL1/EL2/EL3 => AArch32 |
|
| EL0 => AARCH32,EL1/EL2/EL3 => AArch64 |
此三類組合存在64bit –> 32bit之間的所謂 Interprocessing 切換 |
| EL0/EL1 => AArch32,EL2/EL3 => AArch64 |
|
| EL0/EL1/EL2 => AArch32,EL3 => AArch64 |
|
| 組合規則 |
|
| 字寬(ELx)<= 字寬(EL(x+1)) { x=0,1,2 } |
原則:上層字寬不能大於底層字寬 |
• 五類經典組合圖示

3.3路由控制
• 如果EL3使用AArch64,則有如下異常路由控制
3.3.1 路由規則
• 路由規則如下圖所示(from ARMv8 Datasheet):

• 規則小結如下:
| 若SPSR_EL1.M[4] == 0,則決定ELO使用AArch64,否則AArch32 |
| 若SCR_EL3.RW == 1,則決定 EL2/EL1 是使用AArch64,否則AArch32 |
| 若SCR_EL3.{EA, FIQ, IRQ} == 1,則所有相應的SError\FIQ\IRQ 中斷都被路由到EL3 |
| 若HCR_EL2.RW == 1,則決定EL1使用AArch64,否則使用AArch32 |
| 若HCR_EL2.{AMO, IMO, FMO} == 1,則EL1/EL0所有對應的SError\FIQ\IRQ中斷都被路由到EL2,同時使能對應的虛擬中斷VSE,VI,VF |
| 若HCR_EL2.TGE == 1,那么會忽略HCR_EL2.{AMO, IMO, FMO}的具體值,直接當成1處理,則EL1/EL0所有對應的SError\FIQ\IRQ中斷都被路由到EL2,同時禁止所有虛擬中斷 |
| 注意: SCR_EL3.{EA, FIQ, IRQ}bit的優先級高於HCR_EL2.{AMO, IMO, FMO} bit優先級,路由優先考慮SCR_EL3 |
3.3.2 IRQ/FIQ/SError路由流程圖

第4章 ARMv8寄存器
寄存器名稱描述
| 位寬 |
分類 |
||
| 32-bit |
Wn(通用) |
WZR(0寄存器) |
WSP(堆棧指針) |
| 64-bit |
Xn(通用) |
XZR(0寄存器) |
SP(堆棧指針) |
4.1 AArch32重要寄存器
| Bit |
描述 |
|
| R0-R14 |
通用寄存器,但是ARM不建議使用有特殊功能的R13,R14,R15當做通用寄存器使用. |
|
| SP_x |
32bit |
通常稱R13為堆棧指針,除了User和Sys模式外,其他各種模式下都有對應的SP_x寄存器:x ={ und/svc/abt/irq/fiq/hyp/mon} |
| LR_x |
稱R14為鏈接寄存器,除了User和Sys模式外,其他各種模式下都有對應的SP_x寄存器:x ={ und/svc/abt/svc/irq/fiq/mon},用於保存程序返回鏈接信息地址,AArch32環境下,也用於保存異常返回地址,也就說LR和ELR是公用一個,AArch64下是獨立的. |
|
| ELR_hyp |
32bit |
Hyp mode下特有的異常鏈接寄存器,保存異常進入Hyp mode時的異常地址 |
| PC |
32bit |
通常稱R15為程序計算器PC指針,AArch32 中PC指向取指地址,是執行指令地址+8,AArch64中PC讀取時指向當前指令地址. |
| CPSR |
32bit |
記錄當前PE的運行狀態數據,CPSR.M[4:0]記錄運行模式,AArch64下使用PSTATE代替 |
| APSR |
32bit |
應用程序狀態寄存器,EL0下可以使用APSR訪問部分PSTATE值 |
| SPSR_x |
32bit |
是CPSR的備份,除了User和Sys模式外,其他各種模式下都有對應的SPSR_x寄存器:x ={ und/svc/abt/irq/fiq/hpy/mon},注意:這些模式只適用於32bit運行環境 |
| 32bit |
EL2特有,HCR.{TEG,AMO,IMO,FMO,RW}控制EL0/EL1的異常路由 |
|
| SCR |
32bit |
EL3特有,SCR.{EA,IRQ,FIQ,RW}控制EL0/EL1/EL2的異常路由,注意EL3始終不會路由 |
| VBAR |
32bit |
保存任意異常進入非Hyp mode & 非Monitor mode的跳轉向量基地址 |
| HVBAR |
32bit |
保存任意異常進入Hyp mode的跳轉向量基地址 |
| MVBAR |
32bit |
保存任意異常進入Monitor mode的跳轉向量基地址 |
| ESR_ELx |
32bit |
保存異常進入ELx時的異常綜合信息,包含異常類型EC等,可以通過EC值判斷異常class |
| PSTATE |
|
不是一個寄存器,是保存當前PE狀態的一組寄存器統稱,其中可訪問寄存器有:PSTATE.{NZCV,DAIF,CurrentEL,SPSel},屬於ARMv8新增內容,主要用於64bit環境下 |
4.1.1 A32狀態下寄存器組織

• 所謂的banked register 是指一個寄存器在不同模式下有對應不同的寄存器,比如SP,在abort模式下是SP_bat,在Und模式是SP_und,在iqr模式下是SP_irq等,進入各種模式后會自動切換映射到各個模式下對應的寄存器.
• R0-R7是所謂的非banked register,R8-R14是所謂的banked register
4.1.1 T32狀態下寄存器組織
| A32使用 Rd/Rn編碼位寬4位 |
T32-32bit使用 Rd/Rn編碼位寬4位 |
T32-16bit使用 Rd/Rn編碼位寬3位 |
| R0 |
R0 |
|
| R1 |
R1 |
R1 |
| R2 |
R2 |
R2 |
| R3 |
R3 |
R3 |
| R4 |
R4 |
R4 |
| R5 |
R5 |
R5 |
| R6 |
R6 |
R6 |
| R7 |
R7 |
R7 |
| R8 |
R8 |
並不是說T32-16bit下沒有R8~R12,而是有限的指令才能訪問到,16bit指令的Rd/Rn編碼位只有3位,所以Rx范圍是R0-R7 |
| R9 |
R9 |
|
| R10 |
R10 |
|
| R11 |
R11 |
|
| R12 |
R12 |
|
| SP (R13) |
SP (R13) |
SP (R13) |
| LR (R14) |
LR (R14) //M |
LR (R14) //M |
| PC (R15) |
PC (R15) //P |
PC (R15) //P |
| CPSR |
CPSR |
CPSR |
| SPSR |
SPSR |
SPSR |
4.2 AArch64重要寄存器
| 寄存器類型 |
Bit |
描述 |
| X0-X30 |
64bit |
通用寄存器,如果有需要可以當做32bit使用:WO-W30 |
| LR (X30) |
64bit |
通常稱X30為程序鏈接寄存器,保存跳轉返回信息地址 |
| SP_ELx |
64bit |
若PSTATE.M[0] ==1,則每個ELx選擇SP_ELx,否則選擇同一個SP_EL0 |
| ELR_ELx |
64bit |
異常鏈接寄存器,保存異常進入ELx的異常地址(x={0,1,2,3}) |
| PC |
64bit |
程序計數器,俗稱PC指針,總是指向即將要執行的下一條指令 |
| SPSR_ELx |
32bit |
寄存器,保存進入ELx的PSTATE狀態信息 |
| NZCV |
32bit |
允許訪問的符號標志位 |
| DIAF |
32bit |
中斷使能位:D-Debug,I-IRQ,A-SError,F-FIQ ,邏輯0允許 |
| CurrentEL |
32bit |
記錄當前處於哪個Exception level |
| SPSel |
32bit |
記錄當前使用SP_EL0還是SP_ELx,x= {1,2,3} |
| HCR_EL2 |
32bit |
HCR_EL2.{TEG,AMO,IMO,FMO,RW}控制EL0/EL1的異常路由 邏輯1允許 |
| SCR_EL3 |
32bit |
SCR_EL3.{EA,IRQ,FIQ,RW}控制EL0/EL1/EL2的異常路由 邏輯1允許 |
| ESR_ELx |
32bit |
保存異常進入ELx時的異常綜合信息,包含異常類型EC等. |
| VBAR_ELx |
64bit |
保存任意異常進入ELx的跳轉向量基地址 x={0,1,2,3} |
| PSTATE |
|
不是一個寄存器,是保存當前PE狀態的一組寄存器統稱,其中可訪問寄存器有:PSTATE.{NZCV,DAIF,CurrentEL,SPSel},屬於ARMv8新增內容,64bit下代替CPSR |
4.3 64、32位寄存器的映射關系
| 64-bit |
64-bit OS Runing AArch32 App |
64-bit |
32-bit |
|
| X0 |
R0 |
X20 |
LR_adt |
|
| X1 |
R1 |
X21 |
SP_abt |
|
| X2 |
R2 |
X22 |
LR_und |
|
| X3 |
R3 |
X23 |
SP_und |
|
| X4 |
R4 |
X24 |
R8_fiq |
|
| X5 |
R5 |
X25 |
R9_fiq |
|
| X6 |
R6 |
X26 |
R10_fiq |
|
| X7 |
R7 |
X27 |
R11_fiq |
|
| X8 |
R8_usr |
X28 |
R12_fiq |
|
| X9 |
R9_usr |
X29 |
SP_fiq |
|
| X10 |
R10_usr |
X30(LR) |
LR_fiq |
|
| X11 |
R11_usr |
SCR_EL3 |
SCR |
|
| X12 |
R12_usr |
HCR_EL2 |
HCR |
|
| X13 |
SP_usr |
VBAR_EL1 |
VBAR |
|
| X14 |
LR_usr |
VBAR_EL2 |
HVBAR |
|
| X15 |
SP_hyp |
VBAR_EL3 |
MVBAR |
|
| X16 |
LR_irq |
DFSR |
||
| X17 |
SP_irq |
ESR_EL2 |
HSR |
|
| X18 |
LR_svc |
|
|
|
| X19 |
SP_svc |
|
|
第5章 異常模型
5.1 異常類型描述
5.1.1 AArch32異常類型
| 異常類型 |
描述 |
默認捕獲模式 |
向量地址偏移 |
| Undefined Instruction |
未定義指令 |
Und mode |
0x04 |
| Supervisor Call |
SVC調用 |
Svc mode |
0x08 |
| Hypervisor Call |
HVC調用 |
Hyp mode |
0x08 |
| Secure Monitor Call |
SMC調用 |
Mon mode |
0x08 |
| Prefetch abort |
預取指令終止 |
Abt mode |
0x0c |
| Data abort |
數據終止 |
Abt mode |
0x10 |
| IRQ interrupt |
IRQ中斷 |
IRQ mode |
0x18 |
| FIQ interrupt |
FIQ中斷 |
FIQ mode |
0x1c |
| Hyp Trap exception |
Hyp捕獲異常 |
Hyp mode |
0x14 |
| Monitor Trap exception |
Mon捕獲異常 |
Mon mode |
0x04 |
5.1.2 AArch64異常類型
可分為同步異常 & 異步異常兩大類,如下表描述:
| Synchronous(同步異常) |
|
| 異常類型 |
描述 |
| Undefined Instruction |
未定義指令異常 |
| Illegal Execution State |
非常執行狀態異常 |
| System Call |
系統調用指令異常(SVC/HVC/SMC) |
| Misaligned PC/SP |
PC/SP未對齊異常 |
| Instruction Abort |
指令終止異常 |
| Data Abort |
數據終止異常 |
| Debug exception |
軟件斷點指令/斷點/觀察點/向量捕獲/軟件單步 等Debug異常 |
| Asynchronous(異步異常) |
|
| 類型 |
描述 |
| SError or vSError |
系統錯誤類型,包括外部數據終止 |
| IRQ or vIRQ |
外部中斷 or 虛擬外部中斷 |
| FIQ or vFIQ |
快速中斷 or 虛擬快速中斷 |
|
異常進入滿足以下條件 |
向量地址偏移表 |
|||
| Synchronous (同步異常) |
IRQ || vIRQ |
FIQ || vFIQ |
SError || vSError |
|
| SP => SP_EL0 && 從Current EL來 |
0x000 |
0x080 |
0x100 |
0x180 |
| SP => SP_ELx && 從Current EL來 |
0x200 |
0x280 |
0x300 |
0x380 |
| 64bit => 64bit && 從Low level EL來 |
0x400 |
0x480 |
0x500 |
0x580 |
| 32bit => 64bit && 從Low level EL來 |
0x600 |
0x680 |
0x700 |
0x780 |
• SP => SP_EL0,表示使用SP_EL0堆棧指針,由PSTATE.SP == 0決定,PSTATE.SP == 1 則SP_ELx;
• 32bit => 64bit 是指發生異常時PE從AArch32切換到AArch64的情況;
5.2異常處理邏輯
5.2.1 寄存器操作
| 流程 |
Note |
| AArch32 State |
|
x = {und/svc/abt/irq/fiq/hyp/mon} |
PE跳轉到哪一種模式通常由路由關系決定 |
| 2、保存異常返回地址到LR_x,用於異常返回用 |
LR也是對應模式的R[14]_x寄存器,32位系統下LR和ELR是同一個寄存器,而64位是獨立的 |
| 3、備份PSTATE 數據到SPSR_x |
異常返回時需要從SPSR_x恢復PSTATE |
| 4、PSTATE 操作: PSTATE.M[4:0]設置為異常模式x PSTATE.{A,I,F} = 1 PSTATE.T = 1,強制進入A32模式 PSTATE.IT[7:2] = “00000” |
PSTATE.M[4]只是對32位系統有效,64為下是保留的,因為64位下沒有各種mode的概念. 異常處理都要切換到ARM下進行; 進入異常時需要暫時關閉A,I,F中斷; |
| 5、據異常模式x的向量偏移跳轉到進入異常處理 |
各個mode有對應的Vector base addr + offset |
| AArch64 state |
|
|
異常返回時需要從SPSR_ELx中恢復PSTATE |
| 2、保存異常進入地址到ELR_ELx,同步異常(und/abt等)是當前地址,而 異步異常(irq/fiq等)是下一條指令地址 |
64位架構LR和ELR是獨立分開的,這點和32位架構有所差別 |
| 3、保存異常原因信息到ESR_ELx |
ESR_ELx.EC代表Exception Class,關注這個bit |
| 4、PE根據目標EL的異常向量表中定義的異常地址強制跳轉到異常處理程序 |
跳轉到哪個EL使用哪個向量偏移地址又路由關系決定 |
| 5、堆棧指針SP的使用由目標EL決定 |
(SPSR_ELx.M[0] == 1) ? h(ELx): t(EL0) |
5.2.2 路由控制
| Execution State |
異步異常(中斷) |
路由控制位、優先級排列. 1允許 0禁止 |
|
AArch32 |
Asynchronous Data Abort (異步數據終止) |
SCR.EA HCR.TGE HCR.AMO |
| IRQ or vIRQ |
SCR.IRQ HCR.TGE HCR.IMO |
|
| FIQ or vFIQ |
SCR.FIQ HCR.TGE HCR.FMO |
|
|
|
||
|
AArch64 |
SError or vSError |
SCR_EL3.EA HCR_EL2.TGE HCR_EL2.AMO |
| IRQ or vIRQ |
SCR_EL3.IRQ HCR_EL2.TGE HCR_EL2.IMO |
|
| FIQ or vFIQ |
SCR_EL3.FIQ HCR_EL2.TGE HCR_EL2.FMO |
|
• 若HCR_EL2.TGE ==1所有的虛擬中斷將被禁止,HCR.{AMO,IMO,FMO} HCR_EL2.{AMO,IMO,FMO}被當成1處理.
5.3流程圖對比
AArch32、AArch64架構下IRQ 和Data Abort 異常處理流程圖對比.
5.3.1 IRQ 流程圖
5.3.1.1 AArch32

5.3.1.2 AArch64


5.3.2 Data Abort 流程圖
5.3.2.1 AArch32

5.3.2.2 AArch64

5.4 源代碼異常入口
5.4.1 C函數入口
|
異常類型 |
AArch32 State |
AArch64 State |
||
| 所在文件 |
C 函數 |
所在文件 |
C 函數 |
|
| Und |
arm/kernel/traps.c |
do_undefinstr |
Arm64/kernel/traps.c |
do_undefinstr |
| Data Abort |
arm/mm/fault.c |
do_DataAbort |
arm64/mm/fault.c |
do_mem_abort |
| IRQ |
arm/kernel/irq.c |
asm_do_IRQ |
arm64/kernel/irq.c |
handle_IRQ |
| FIQ |
|
|
|
|
| System Call |
|
|
|
|
|
|
|
|
|
|
5.4.2 上報流程圖
例舉Data Abort 和 IRQ中斷的入口流程圖
5.4.2.1 Data Abort 上報

5.4.2.2 IRQ上報

5.4.3 異常進入壓棧准備
分析64位kernel_entry 壓棧代碼邏輯(代碼路徑:kernel/arch/arm64/kernel/entry.S)
| • sp指向 #S_LR – #S_FRAME_SIZE 位置 |
#S_FRAME_SIZE是pt_regs結構圖的size |
| • 依次把x28-x29 … x0-x1 成對壓入棧內 |
每壓入一對寄存器,sp指針就移動 -16 =((64/8)*2)字節長度,棧是向地址減少方向增長的. |
| • 保存sp+#S_FRAME_SIZE數據到x21 |
add x21, sp, #SP_FRAME_SIZE |
| • 保存elr_el1到x22 |
mrs x22, elr_el1 |
| • 保存spsr_el1到x23 |
mrs x23, spsr_el1 |
| • 把lr、x21寫入sp+#S_LR地址內存 |
保存lr和x21的數據到指定棧內存位置 |
| • 把x22、x23寫入sp+#S_PC地址內存 |
保存elr,spsr數據到指定棧內存位置 |
5.4.4 棧布局
第6章 ARMv8指令集
6.1 概況
• A64指令集
• A32 & T32指令集
• 指令編碼
6.1.1 指令基本格式
<Opcode>{<Cond>}<S> <Rd>, <Rn> {,<Opcode2>}
• 其中尖括號是必須的,花括號是可選的
• A32: Rd => {R0–R14}
• A64: Rd =>Xt => {X0–X30}
| 標識符 |
Note |
| Opcode |
操作碼,也就是助記符,說明指令需要執行的操作類型 |
| Cond |
指令執行條件碼,在編碼中占4bit,0b0000 -0b1110 |
| S |
條件碼設置項,決定本次指令執行是否影響PSTATE寄存器響應狀態位值 |
| Rd/Xt |
目標寄存器,A32指令可以選擇R0-R14,T32指令大部分只能選擇RO-R7,A64指令可以選擇X0-X30 or W0-W30 |
| Rn/Xn |
第一個操作數的寄存器,和Rd一樣,不同指令有不同要求 |
| Opcode2 |
第二個操作數,可以是立即數,寄存器Rm和寄存器移位方式(Rm,#shit) |
6.1.2 指令分類
| 類型 |
Note |
| • 跳轉指令 |
條件跳轉、無條件跳轉(#imm、register)指令 |
| • 異常產生指令 |
系統調用類指令(SVC、HVC、SMC) |
| • 系統寄存器指令 |
讀寫系統寄存器,如 :MRS、MSR指令 可操作PSTATE的位段寄存器 |
| • 數據處理指令 |
包括各種算數運算、邏輯運算、位操作、移位(shift)指令 |
| • load/store 內存訪問指令 |
load/store {批量寄存器、單個寄存器、一對寄存器、非-暫存、非特權、獨占}以及load-Acquire、store-Release指令 (A64沒有LDM/STM指令) |
| • 協處理指令 |
A64沒有協處理器指令 |
6.2 A64指令集
| • A64指令編碼寬度固定32bit |
| • 31個(X0-X30)個64bit通用用途寄存器(用作32bit時是W0-W30),寄存器名使用5bit編碼 |
| • PC指針不能作為數據處理指或load指令的目的寄存器,X30通常用作LR |
| • 移除了批量加載寄存器指令 LDM/STM, PUSH/POP, 使用STP/LDP 一對加載寄存器指令代替 |
| • 增加支持未對齊的load/store指令立即數偏移尋址,提供非-暫存LDNP/STNP指令,不需要hold數據到cache中 |
| • 沒有提供訪問CPSR的單一寄存器,但是提供訪問PSTATE的狀態域寄存器 |
| • 相比A32少了很多條件執行指令,只有條件跳轉和少數數據處理這類指令才有條件執行. |
| • 支持48bit虛擬尋址空間 |
| • 大部分A64指令都有32/64位兩種形式 |
| • A64沒有協處理器的概念 |
6.2.1 指令助記符
| 整型 |
|
| W/R |
32bit整數 |
| X |
64bit整數 |
| 加載/存儲、符號-0擴展 |
|
| B |
無符號8bit字節 |
| SB |
帶符號8bit字節 |
| H |
無符號16bit半字 |
| SH |
帶符號16bit半字 |
| W |
無符號32bit字 |
| SW |
帶符號32bit字 |
| P |
Pair(一對) |
| 寄存器寬度改變 |
|
| H |
高位(dst gets top half) |
| N |
有限位(dst < src) |
| L |
Long (dst > src) |
| W |
Wide (dst==src1,src1>src2) ? |
6.2.2 指令條件碼
| 編碼 |
助記符 |
描述 |
標記 |
| 0000 |
EQ |
運算結果相等為1 |
Z==1 |
| 0001 |
NE |
運算結果不等為0 |
Z==0 |
| 0010 |
HS/CS |
無符號高或者相同進位,發生進位為1 |
C==1 |
| 0011 |
LO/CC |
無符號低清零,發生借位為0 |
C==0 |
| 0100 |
MI |
負數為1 |
N==1 |
| 0101 |
PL |
非負數0 |
N==0 |
| 0110 |
VS |
有符號溢出為1 |
V==1 |
| 0111 |
VC |
沒用溢出為0 |
V==0 |
| 1000 |
HI |
無符號 > |
C==1 && Z==0 |
| 1001 |
LS |
無符號 <= |
!(C==1 && Z==0) |
| 1010 |
GE |
帶符號 >= |
N==V |
| 1011 |
LT |
帶符號 < |
N!=V |
| 1100 |
GT |
帶符號 > |
Z==0 && N==V |
| 1101 |
LE |
帶符號 <= |
!( Z==0 && N==V) |
| 1110 |
AL |
無條件執行 |
Any |
| 1111 |
NV |
6.2.3 跳轉指令
6.2.3.1 條件跳轉
| cond為真跳轉 |
|
| CBNZ |
CBNZ X1,label //如果X1!= 0則跳轉到label |
| CBZ |
CBZ X1,label //如果X1== 0則跳轉到label |
| TBNZ |
TBNZ X1,#3 label //若X1[3]!=0,則跳轉到label |
| TBZ |
TBZ X1,#3 label //若X1[3]==0,則跳轉到label |
6.2.3.2 絕對跳轉
| 絕對跳轉 |
|
| BL |
絕對跳轉 #imm,返回地址保存到LR(X30) |
| BLR |
絕對跳轉reg,返回地址保存到LR(X30) |
| BR |
跳轉到reg內容地址, |
| RET |
子程序返回指令,返回地址默認保存在LR(X30) |
6.2.4 異常產生和返回指令
| SVC系統調用,目標異常等級為EL1 |
|
| HVC |
HVC系統調用,目標異常等級為EL2 |
| SMC |
SMC系統調用,目標異常等級為EL3 |
| ERET |
異常返回,使用當前的SPSR_ELx和ELR_ELx |
6.2.5 系統寄存器指令
| R <- S: 通用寄存器 <= 系統寄存器 |
|
| MSR |
S <- R: 系統寄存器 <= 通用寄存器 |
6.2.6 數據處理指令
| 數據處理指令類型 |
|||||
| 算數運算 |
邏輯運算 |
數據傳輸 |
地址生成 |
位段移動 |
移位運算 |
| ADDS |
ANDS |
MOV |
ADRP |
BFM |
ASR |
| SUBS |
EOR |
MOVZ |
ADR |
SBFM |
LSL |
| CMP |
ORR |
MOVK |
|
UBFM |
LSR |
| SBC |
MOVI |
|
|
BFI |
ROR |
| RSB |
TST |
|
|
BFXIL |
|
| RSC |
|
|
|
SBFIZ |
|
|
|
|
|
SBFX |
|
|
| MADD |
|
|
|
UBFIZ |
|
|
|
|
|
|
|
|
| MUL |
|
|
|
|
|
| SMADDL |
|
|
|
|
|
| SDIV |
|
|
|
|
|
| UDIV |
|
|
|
|
|
6.2.6.1 算術運算指令
| ADDS |
加法指令,若S存在,則更新條件位flag |
| ADCS |
帶進位的加法,若S存在,則更新條件位flag |
| SUBS |
減法指令,若S存在,則更新條件位flag |
| 將操作數 1 減去操作數 2,再減去 標志位C的取反值 ,結果送到目的寄存器Xt/Wt |
|
| RSB |
逆向減法,操作數 2 –操作數 1,結果 Rd |
| RSC |
帶借位的逆向減法指令,將操作數 2 減去操作數 1,再減去 標志位C的取反值 ,結果送目標寄存器Xt/Wt |
| CMP |
比較相等指令 |
| CMN |
比較不等指令 |
| NEG |
取負數運算,NEG X1,X2 // X1 = X2按位取反+1(負數=正數補碼+1) |
| MADD |
|
| MSUB |
乘減運算 |
| MUL |
乘法運算 |
| SMADDL |
有符號乘加運算 |
| SDIV |
有符號除法運算 |
| UDIV |
無符號除法運算 |
6.2.6.2 邏輯運算指令
| ANDS |
按位與運算,如果S存在,則更新條件位標記 |
| EOR |
按位異或運算 |
| ORR |
按位或運算 |
| TST |
例如:TST W0, #0X40 //指令用來測試W0[3]是否為1,相當於:ANDS WZR,W0,#0X40 |
6.2.6.3 數據傳輸指令
| MOV |
賦值運算指令 |
| 賦值#uimm16到目標寄存器Xd |
|
| MOVN |
賦值#uimm16到目標寄存器Xd,再取反 |
| MOVK |
賦值#uimm16到目標寄存器Xd,保存其它bit不變 |
6.2.6.4 地址生成指令
| ADRP |
base = PC[11:0]=ZERO(12); Xd = base + label; |
| ADR |
Xd = PC + label |
6.2.6.5 位段移動指令
| BFM Wd, Wn, #r, #s if s>=r then Wd<s-r:0> = Wn<s:r>, else Wd<32+s-r,32-r> = Wn<s:0>. |
|
| SBFM |
|
| UBFM |
|
| BFI |
|
| BFXIL |
|
| SBFIZ |
|
| SBFX |
|
| UBFX |
|
| UBFZ |
|
6.2.6.6 移位運算指令
| ASR |
算術右移 >> (結果帶符號) |
| LSL |
邏輯左移 << |
| LSR |
邏輯右移 >> |
| ROR |
循環右移:頭尾相連 |
| 字節、半字、字符號/0擴展移位運算 關於SXTB #imm和UXTB #imm 的用法可以使用以下圖解描述: |
|
| SXTH |
|
| SXTW |
|
| UXTB |
|
| UXTH |


6.2.7 Load/Store指令
| 對齊 偏移 |
非對齊 偏移 |
PC-相對 尋址 |
訪問 一對 |
非暫存 |
非特權 |
獨占 |
Acquire Release |
| LDR |
LDUR |
LDR |
LDP |
LDNP |
LDTR |
LDXR |
LDAR |
| LDRB |
LDURB |
LDRSW |
LDRSW |
STNP |
LDTRB |
LDXRB |
LDARB |
| LDRSB |
LDURSB |
|
STP |
|
LDTRSB |
LDXRH |
LDARH |
| LDRH |
LDURH |
|
|
|
LDTRH |
LDXP |
STLR |
| LDRSH |
LDURSH |
|
|
|
LDTRSH |
STXR |
STLRB |
| LDRSW |
LDURSW |
|
|
|
LDTRSW |
STXRB |
STLRH |
| STR |
STUR |
|
|
|
STTR |
STXRH |
LDAXR |
| STRB |
STURB |
|
|
|
STTRB |
STXP |
LDAXRB |
| STRH |
STURH |
|
|
|
STTRH |
|
LDAXRH |
|
|
|
|
|
|
|
|
LDAXP |
|
|
|
|
|
|
|
|
STLXR |
|
|
|
|
|
|
|
|
STLXRB |
|
|
|
|
|
|
|
|
STLXRH |
|
|
|
|
|
|
|
|
STLXP |
6.2.7.1 尋址方式
| 類型 |
立即數偏移 |
寄存器偏移 |
擴展寄存器偏移 |
| { base{,#0 } } |
|
|
|
| 基址寄存器 (+ 偏移) |
{ base{,#imm } } |
{ base,Xm{,LSL #imm } } |
[base,Wm,(S|U)XTW {#imm }] |
| Pre-indexed (事先更新) |
[ base,#imm ]! |
|
|
| Post-indexed (事后更新) |
[ base,#imm ] |
{ base },Xm |
|
| PC-相對尋址 |
label |
|
|
6.2.7.2 Load/Store (Scaled Offset)
| 支持的尋址方式 |
| 對齊的,無符號#imm12偏移,不支持pre-/post-index 操作 |
| 非對齊,帶符號#imm9偏移,支持pre-/post-index 操作 |
| 對齊or非對齊的64bit寄存器偏移 |
| 對齊or 非對齊的32bit寄存器偏移 |
| Zero-Extend / Sign-Extend |
|
| 0 擴展 |
從Memory讀取一個無符號32位Wn數據寫到一個64位Xt寄存器中,Wn數據被存儲到Xt[31:0],Xt[63:32]使用0代替 |
| 符號擴展 |
從Memory讀取一個有符號32位Wn數據寫到一個64位Xt寄存器中,Wn數據被存儲到Xt[31:0],Xt[63:32]使用Wn的符號位值(Wn[31])代替 |
| LDR |
從Memory地址addr中讀取雙字/字節/半字/字數據到目標寄存器Xt/Wt中 帶”S”表示需要符號擴展. |
| LDRB |
|
| LDRSB |
|
| LDRH |
|
| LDRSH |
|
| LDRSW |
|
| STR |
把Xn/Wn中的雙字/字節/半字數據寫入到Memory地址addr中 |
| STRB |
|
| STRH |
6.2.7.3 Load/Store (Unscaled Offset)
• 所謂Scaled 和Unscaled其實就是可以見到理解為對齊和非對齊,本質就是是否乘以一個常量,因為scaled的總是可以乘以一個常量來達到對齊,而Unscaled就不需要,是多少就多少,更符合人類自然的理解
| 支持的尋址方式 |
| • 非對齊的,有符號#simm9偏移,不支持pre-/post-index 操作 |
| 從Memory地址addr中讀取雙字/字節/半字/字數據到目標寄存器Xt/Wt中 帶”S”表示需要符號擴展. 立即數偏移 #simm9 = { -256 ~ +256 } 的任意整數,不需要對齊規則. |
|
| LDURB |
|
| LDURSB |
|
| LDURH |
|
| LDURSH |
|
| LDURSW |
|
| STUR |
把Xn/Wn中的雙字/字節/半字數據寫入到Memory地址addr中 立即數偏移 #simm9 = { -256 ~ +256 } 的任意整數,不需要對齊規則. |
| STURB |
|
| STURH |
6.2.7.4 Load/Store PC-relative(PC相對尋址)
| 支持的尋址方式 |
| • 不支持pre-/post-index 操作 |
| LDR |
從Memory地址addr中讀取雙字/字數據到目標寄存器Xt/Wt中 帶”S”表示需要符號擴展. |
| LDRSW |
6.2.7.5 Load/Store Pair(一對)
| 支持的尋址方式 |
| • 對齊的,有符號#simm7偏移,支持pre-/post-index 操作 |
| LDP |
從Memory地址addr處讀取兩個雙字/字數據到目標寄存器Xt1,Xt2 帶”S”表示需要符號擴展. |
| LDRSW |
|
| STP |
把Xt1,Xt2兩個雙字/字數據寫到Memory地址addr中 |
6.2.7.6 Load/Store Non-temporal(非暫存) Pair
• 所謂Non-temporal就是就是用於你確定知道該地址只加載一次,不需要觸發緩存,避免數據被刷新,優化性能,其它指令都默認會寫Cache
| • 對齊的,有符號#simm7偏移,不支持pre-/post-index 操作 |
| LDNP |
從Memory地址addr處讀取兩個雙字/字數據到目標寄存器Xt1,Xt2, 標注非暫存訪問,不更新cache 帶”S”表示需要符號擴展. |
| STNP |
把Xt1,Xt2兩個雙字/字數據寫到Memory地址addr中,標注非暫存訪問,不更新cache |
6.2.7.7 Load/Store Unprivileged(非特權)
• 所謂Unprivileged就是說EL0/EL1的內存有不同的權限控制,這條指令以EL0的權限存取,用於模擬EL0的行為,該指令應用於EL1和EL0之間的交互.
| • 非對齊的,有符號#simm9偏移,不支持pre-/post-index 操作 |
| 從Memory地址addr中讀取雙字/字節/半字/字數據到目標寄存器Xt/Wt中, 當執行在EL1的時候使用EL0的權限 帶”S”表示需要符號擴展
|
|
| LDTRB |
|
| LDTRSB |
|
| LDTRH |
|
| LDTRSH |
|
| LDTRSW |
|
| STTR |
把Xn/Wn中的雙字/字節/半字數據寫入到Memory地址addr中, 當執行在EL1的時候使用EL0的權限 |
| STTRB |
|
| STTRH |
6.2.7.8 Load/Store Exclusive(獨占)
• 在多核CPU下,對一個地址的訪問可能引起沖突,這個指令解決了沖突,保證原子性(所謂原子操作簡單理解就是不能被中斷的操作),是解決多個CPU訪問同一內存地址導致沖突的一種機制。
比如2個CPU同時寫,其中一條的Ws就會返回失敗值。通常用於鎖,比如spinlock,可以參考代碼:arch/arm64/include/asm/spinlock.h
| • 無偏移基址寄存器,不支持pre-/post-index 操作 |
| 從Memory地址addr中讀取雙字/字節/半字數據到目標寄存器Xt/Wt中, 標記物理地址是獨占訪問的 |
|
| LDXRB |
|
| LDXRH |
|
| LDXP |
從Memory地址addr中讀取一對雙字數據到目標寄存器Xt1,Xt2中,標記物理地址是獨占訪問的 |
| STXR |
把Xn/Wn中的雙字/字節/半字數據寫入到Memory地址addr中, 返回是否獨占訪問成功狀態(Ws) |
| STXRB |
|
| STXRH |
|
| STXP |
把Xt1,Xt2一對雙字字數據寫入到Memory地址addr中,返回是否獨占訪問成功狀態 |
6.2.7.9 Load-Acquire/Store-Release
| Load-Acquire Acquire的語義是讀操作 |
相當於半個DMB指令,只管讀內存操作 |
| Store-Release Release的語義是寫操作 |
相當於半個DMB指令,只管寫內存操作 |
| 支持的尋址方式 |
| • 無偏移基址寄存器,不支持pre-/post-index 操作 |
| Non-exclusive(非獨占) |
|
| LDAR |
從Memory地址addr中讀取一個雙字/字節/半字數據到目標寄存器Xt/Wt中, 標記物理地址為非獨占訪問 |
| LDARB |
|
| LDARH |
|
| STLR |
把一個雙字/字節/半字數據Xt/Wt寫到Memory地址addr中, 返回是否獨占訪問成功狀態
|
| STLRB |
|
| STLRH |
|
| Exclusive(獨占) |
|
| LDAXR |
從Memory地址addr中讀取一個雙字/字節/半字數據到目標寄存器Xt/Wt中, 標記物理地址為獨占訪問
LDAXP 是Pair 訪問 |
| LDAXRB |
|
| LDAXP |
|
| STLXR |
把一個雙字/字節/半字數據Xt/Wt寫到Memory地址addr中, 返回是否獨占訪問成功狀態
STLXP 是Pair 訪問 |
| STLXRB |
|
| STLXP |
|
6.2.8 屏障指令
| DMB |
數據內存屏障指令 |
保證該指令前的所有內存訪問結束,而該指令之后引起的內存訪問只能在該指令執行結束后開始,其它數據處理指令等可以越過DMB屏障亂序執行 |
| DSB |
數據同步屏障指令 |
DSB比DMB管得更寬,DSB屏障之后的所有得指令不可越過屏障亂序執行 |
| ISB |
指令同步屏障指令 |
ISB比DSB管的更寬,ISB屏障之前的指令保證執行完,屏障之后的指令直接flush掉再重新從Memroy中取指 |
• 以DMB指令為例介紹屏障指令原理.
| ADD X1,X2,X3 ------(A) LDR X4,addr ------(B) STR X6,addr2 DMB <option> -----(DMB) LDR X5,addr3 ------(C) STR X7,addr4 SUB X8,X9,#2 ------(D) |
左邊程序中,因為有(DMB)的屏障作用,(C)必須要等(B)執行完成后才可以執行,保證執行順序。而(A)、(D)不屬於Memory access指令,可以越過DMB屏障 亂序執行;
|
| 而結合到Load-Acquire/Store-Release,可以分別理解為半個DMB指令,Load-Acquire只管Memory read,而Store-Release只管Memroy write,組合使用可以增加代碼亂序執行的靈活性和執行效率. |
6.3 A32 & T32指令集
6.3.1 跳轉指令
| 條件跳轉 |
|
| BL |
跳轉前會把當前指令的下一條指令保存到 R14 (lr) |
| BX |
只能用於寄存器尋址,寄存器最低位值用於切換 ARM/Thumb 工作狀態,ARM/Thumb 的切 換只能通過跳轉實現,不能通過直接 write register 方式實現. |
| BLX |
BL & BX 的並集 |
| CBNZ |
比較非 0 跳轉 |
| CBZ |
比較為 0 跳轉 |
| TBNZ |
測試位比較非 0 跳轉 |
| TBZ |
測試位比較 0 跳轉 |
| BLR |
帶返回的寄存器跳轉 |
| BR |
跳轉到寄存器 |
| RET |
返回到子程序 |
6.3.2 異常產生、返回指令
• 參考A64指令集.
6.3.3 系統寄存器指令
• 參考A64指令集.
6.3.4 系統寄存器指令
• 參考A64指令集.
6.3.5 數據處理指令
• 參考A64指令集.
6.3.6 Load/Store指令
6.3.6.1 尋址方式
| Offset addressing |
偏移尋址(reg or #imm) |
[ <Rn>, <offset>] |
| Pre-indexed addressing |
事先更新尋址,先變化后操作 |
[ <Rn>, <offset>]! |
| Post-indexed addressing |
事后更新尋址,先操作后變化 |
[<Rn>], <offset> |
6.3.6.2 Load /Store
| Normal |
非特權 |
獨占 |
Load Acquire |
Store Release |
獨占 |
||||
| Acquire |
Release |
||||||||
| LDR |
STR |
LDRT |
STRT |
STREX |
LDA |
STL |
LDAEX |
STLEX |
|
| LDRH |
STRH |
LDRHT |
STRHT |
LDREXH |
STREXH |
LDAH |
STLH |
LDAEXH |
STLEXH |
| LDRSH |
|
LDRSHT |
|
|
|
|
|
|
|
| LDRB |
STRB |
LDRBT |
STRBT |
LDREXB |
STREXB |
LDAB |
STLB |
LDAEXB |
STLEXB |
| LDRSB |
|
LDRSBT |
|
|
|
|
|
|
|
| LDRD |
STRD |
|
|
LDREXD |
SETEXD |
|
|
LDAEXD |
|
• LDRD/ STRD 和A64的LDP/STP 用法類似,表中的D(Dua)關鍵字和A64的P(Pair)關鍵字是一個意思,都是指操作一對寄存器.
• 以上指令用法和A64類似.
6.3.6.3 Load /Store(批量)
| LDM |
LDM {Cond} {類型} 基址寄存器{!},寄存器列表{^} 從指定內存中加載批量數據到寄存器堆 |
| STM |
STM {Cond} {類型} 基址寄存器{!},寄存器列表{^} 把寄存器堆中批量數據存儲到指定內存地址 |
| PUSH |
批量壓入棧 |
| POP |
批量彈出棧 |
| 類型 |
助記符 |
指令 |
Note |
| 地址 變化 方式 |
IA |
LDMIA/STMIA |
先操作,后遞增4字節 |
| IB |
LDMIB/STMIA |
||
| DA |
LDMDA/STMDA |
先操作,后遞減4字節 |
|
| DB |
LDMDB/STMDB |
先遞減4字節,后操作 |
|
| FD |
LDMFD/STMFD |
滿遞減堆棧,SP指向最后一個元素 |
|
| FA |
LDMFA/STMFA |
滿遞增堆棧,SP指向最后一個元素 |
|
| ED |
LDMED/STMED |
空遞減堆棧,SP指向將要壓入數據的空地址 |
|
| EA |
LDMEA/STMEA |
空遞增堆棧,SP指向將要壓入數據的空地址 |
•關於數據棧類型
| 滿遞減 |
堆棧首部是高地址,堆棧向低地址增長。SP總是指向堆棧最后一個元素(最后一個元素是最后壓入的數據) |
| 滿遞增 |
堆棧首部是低地址,堆棧向高地址增長。SP總是指向堆棧最后一個元素(最后一個元素是最后壓入的數據) |
| 空遞減 |
堆棧首部是低地址,堆棧向高地址增長。SP總是指向下一個將要放入數據的空位置 |
| 空遞增 |
堆棧首部是高地址,堆棧向低地址增長。SP總是指向下一個將要放入數據的空位置 |

| • LDM/STM可以實現一次在一片連續的存儲器單元和多個寄存器之間傳送數據,批量加載指令用於將一片連續的存儲器中的數據傳送到多個寄存器,批量存儲指令完成相反的操作 |
|
| • {!}為可選后綴,若選用,則當數據傳送完畢之后,將最后的地址寫入基址寄存器,否則基址寄存器的內容不改變,基址寄存器不允許為R15(PC),寄存器列表可以為R0 ~ R15的任意組合 |
|
| • {^}為可選后綴,當指令為LDM且寄存器列表中包含有R15,選用該后綴表示:除了正常的數據傳送之外,還將SPSR復制到CPSR,同時,該后綴還表示傳入或傳出的是用戶模式下的寄存器,而不是當前模式下的寄存器 |
|
| LDMIA R0!, {R1-R4} // R1<----[R0] // R2<----[R0 + 4] // R3<----[R0 + 8] // R4<----[R0 + 12] |
LDMIA R0!, {R1-R4} // R1<----[R0] // R2<----[R0 + 4] // R3<----[R0 + 8] // R4<----[R0 + 12] |
| STMFD SP!,{R0-R3} //[R0]<----[SP] //[R1]<----[SP + 4] //[R2]<----[SP + 8] //[R3]<----[SP + 12] |
LDMFD SP!, {R6-R8} // R6<----[SP] // R7<----[SP + 4] // R8<----[SP + 8] |
6.3.7 IT(if then)指令
• 基本格式:IT{<x>{<y>{<z>}}}{<q>} <cond>
• T32中的IT指令用於根據特定條件來執行緊跟其后的1-4條指令,其中X,Y,Z分別是執行第二、三、四條指令的條件,可取的值為T(then)或E(else),<cond>條件的值控制指令的執行邏輯.
T表示<cond>條件為TRUE則執行對應指令,E 表示<cond>為FALSE執行對應指令,如下例子描述.
| ITETT EQ |
據EQ(N==1)的條件是否成立判斷,2、3、4執行邏輯分別是E、T、T |
| MOVEQ R0, #1 // 1 |
若EQ為真(N==1),則執行 1、3、4(T)的MOV操作,否則執行2(E)的MOV操作 E T T |
| MOVNE R0, #0 // 2 |
|
| MOVEQ R1, #0 // 3 |
|
| MOVEQ R2, #0 // 4 |
6.3.8 協處理器指令
| 數據操作指令,用於ARM通知協處理器執行特定操作 |
|
| LDC |
數據加載指令,用於源寄存器所指向的Mem數據傳送到目標寄存器 |
| STC |
數據存儲指令,用於源寄存器所指向的數據傳送到目標寄存器所指向的Mem中 |
| MCR |
數據傳送指令,ARM寄存器 => 協處理器寄存器 |
| MRC |
數據傳送指令,ARM寄存器 <= 協處理器寄存器 |
6.4 指令編碼
• A32
• T32-16bit
• T32-32bit
• A64
6.4.1 A32編碼
• 基本格式
![]()
| 位於[31:28] 的4bit寬條件碼 |
| op1位段控制指令類型:數據處理、load/store、跳轉、協處理器指令… |
| Rd/Rn寬度為4bit,寄存器可訪問范圍R0-R15 ,R15(PC)通常不做通用寄出去用途. |
6.4.2 T32-16bit編碼
• 基本格式

| 固定13bit編碼,要求半字對齊 |
| 位於[15:10] 的5bit決定指令類型,詳見Datasheet F3.4/P2475. |
| 沒用cond條件碼位. |
| Rd/Rn寬度為3bit,寄存器可訪問范圍R0-R7 |
6.4.3 T32-32bit編碼
• 基本格式

| 固定32bit寬編碼,由兩個連續16bit半字組合而成,要求半字對齊 |
| 第一個半字的高三位固定為111,Op2位段決定指令類型, |
| 如果op1 == 00,那么表示會被編碼位16bit指令,否則是32bit指令 |
| Rd/Rn寬度為4bit,寄存器可訪問范圍R0-R14 |
6.4.4 A64編碼

| 固定32bit寬編碼,若sf == 0則表示32bit指令,否則表示64bit指令 |
| Rd/Rn寬度為5bit,寄存器可訪問范圍X0-X30 |
| 對比A32指令很少cond位. |
| 詳細參考Datasheet C4章節. |
6.4 匯編代碼分析
• 以memcpy.S為例,分析筆記如下:
![]()
http://note.youdao.com/share/?id=f7976e6571ceae443da4e36d28842dcb&type=note
7.1 簡介
| 1、不能減少單指令的響應時間,和single-cycle指令的響應時間是相同的 |
| 2、多指令同時使用不同資源,可提升整體單cycle內的指令吞吐量,極大提高指令執行效率 |
| 3、指令執行速率被最慢的流水線級所限制,執行效率被依賴關系限制影響 |
7.1.1 簡單三級流水線
| IF |
Instruction fetch |
取指 |
| ID |
Instruction decode & register file read |
譯碼 & 讀取寄存器堆數據 |
| EX |
Execution or address calculation |
執行 or 地址計算 |
圖示:

7.1.2 經典五級流水線
| IF |
Instruction fetch |
取指 |
| ID |
Instruction decode & register file read |
譯碼 & 讀取寄存器堆數據 |
| EX |
Execution or address calculation |
執行 or 地址計算 |
| MEM |
Data memeory access |
讀寫內存數據 |
| WB |
Write back |
數據寫回到寄存器堆 |
圖示:

7.2 流水線沖突
| 類型 |
Note |
解決方法 |
| 結構沖突 |
不同指令同時占用問儲器資源沖突,早期處理器程序、數據存儲器混合設計產生的問題。 |
分離程序、數據存儲器,現代處理器已不存在這種沖突 |
|
數據沖突 |
不同指令同時訪問同一寄存器導致,通常發生在寄存器 RAW(read after write)的情況下, WAR(write after read) & WAW(write after write) 的情況再ARM不會發生. |
• SW插入NOP,增加足夠的cycle等待,但是對CPU性能有大影響 • HW 使用forwarding(直通)解決,對性能影響小 |
|
控制沖突 |
B指令跳轉,導致其后面的指令的fetch等操作變成無用功,因此跳轉指令會極大影響CPU性能. |
• SW插入NOP,增加足夠的cycle等待,同樣對CPU性能有大影響 |
7.3 指令並行
• 指令並行提升方法
| 1、增加單條流水線深度,若是N級流水線,那么在single-cycle內有N條指令被執行. |
| 2、Pipeline並行,若有M條流水線,每條流水線深度為N,那么single-cycle內有M*N條指令被執行,極大提升指令執行效率. |
