|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 行者~ABC 于 2021-1-7 10:05 编辑 % l+ r) q& A9 c' n7 t+ M5 H" j0 ^7 B
1 ]' }; U# t- p, L4 D
H, v7 P5 T H, F. I* M2 r5 C; o0 R
ARM Cortex-M4 支持的指令在下表 1~8 中列出。
6 P9 E9 J9 w# M* z5 J1 j2 h$ J( R) V0 x% Z& \
表 1 16 位数据操作指令0 J$ }2 \* H; ?7 l8 a
指令 功能7 E( d l( ]- {! e0 e. R, l
ADC 带进位加法
1 X# s n+ U0 m R) }; ~5 _ ADD 加法2 N0 {% y+ v" t% z# t- l) M1 v' ?; Q
AND 按位与。这里的按位与和 C 的”&”功能相同: ]$ c, S, j) v( j6 D1 j: E
ASR 算术右移
$ }$ S, a* P4 F% U. t+ t: F; u BIC 按位清 0(把一个数跟另一个无符号数的反码按位与)" u1 E0 _3 R9 b: \! L' n
CMN 负向比较(把一个数跟另一个数据的二进制补码相比较)! i2 V! J( l% h5 B
CMP 比较(比较两个数并且更新标志)8 r! \" O2 P' e- @+ K! @. P
CPY 把一个寄存器的值拷贝到另一个寄存器中
9 [- z) B, {* B7 Q EOR 近位异或
6 p1 ^. o" ]6 r; B$ ^# I) x LSL 逻辑左移(如无其它说明,所有移位操作都可以一次移动多格)- o( ^2 W7 l* i
LSR 逻辑右移
0 Z( ~" A5 q8 p' u) A MOV 寄存器加载数据,既能用于寄存器间的传输,也能用于加载立即数
' R: B5 @. G* d- n" J4 J MUL 乘法/ U8 n2 K) a* B! W" X& f; d
MVN 加载一个数的 NOT 值(取到逻辑反的值)6 Z( F: ]" X& s' g; D
NEG 取二进制补码
7 B3 j% b% p6 l$ D. o O ORR 按位或5 f' p. @. L3 Y
ROR 圆圈右移0 s) `/ J- J$ `' D
SBC 带借位的减法/ Q ]$ ~0 i8 o$ a/ q: L4 T7 v0 ^8 }
SUB 减法
0 I8 h( w+ {4 M& R( v% @ TST 测试(执行按位与操作,并且根据结果更新 Z)) e5 G" E( U3 g& |6 {5 s; r
REV 在一个 32 位寄存器中反转字节序
# W2 L: z4 p" h REVH 把一个 32 位寄存器分成两个 16 位数,在每个 16 位数中反转字节序
; H2 o0 M& ^. U3 A1 s REVSH 把一个 32 位寄存器的低 16 位半字进行字节反转,然后带符号扩展到 32 位, V0 ~& W' T, |5 I, l; _& m+ }: w
SXTB 带符号扩展一个字节到 32 位' u5 Y+ U& O: {6 }2 u% w, H0 O0 @" q
SXTH 带符号扩展一个半字到 32 位- y2 i# t8 h- V- j" O
UXTB 无符号扩展一个字节到 32 位& R$ ~( E5 c* m* O' ?1 l
UXTH 无符号扩展一个半字到 32 位9 P+ @/ J. `; U' V
% N1 Z, o# U* h$ V" ^5 C+ Q
表 2 16 位转移指令: b I9 {, y) [, n( m0 M
指令 功能
! X$ r; `! M$ v B 无条件转移, L5 G0 n1 U: Q8 Y% d! F
B<cond> 条件转移
~' ^, h! m' r5 M- ~+ b5 b: a5 x' x BL 转移并链接。用于呼叫一个子程序,返回地址被存储在 LR 中- N6 w6 b+ U8 t. b+ V" Y- E( ^; l
BLX 使用立即数的 BLX 不要在 ARM Cortex-M4 中使用
2 ^2 y' `/ `8 z- I& n6 d CBZ 比较,如果结果为 0 就转移(只能跳到后面的指令)
+ Y4 `( R9 V3 q9 t# K& W U6 Q CBNZ 比较,如果结果非 0 就转移(只能跳到后面的指令)
0 D# Y0 L& B) C( R6 n+ \: R IT If‐Then: U2 E# \" C" V8 V8 y6 P
0 z7 v/ w1 h0 o" X. a
表 3 16 位存储器数据传送指令
& C5 _; C, v. P# b5 I5 Z/ W 指令 功能1 w5 \) d5 Q) z; t3 M
LDR 从存储器中加载字到一个寄存器中7 R- Q& P2 Z6 ?
LDRH 从存储器中加载半字到一个寄存器中
7 A( v. f6 O* H8 Y LDRB 从存储器中加载字节到一个寄存器中! T9 C+ O3 _# t
LDRSH 从存储器中加载半字,再经过带符号扩展后存储一个寄存器中7 n Z3 [! n, V& ^! }6 L
LDRSB 从存储器中加载字节,再经过带符号扩展后存储一个寄存器中
6 _) b# K( x2 G8 H7 H' g STR 把一个寄存器按字存储到存储器中, n, R4 f- H" o. O( b1 z
STRH 把一个寄存器存器的低半字存储到存储器中- X# D% ~* Z# e2 ~) I/ U
STRB 把一个寄存器的低字节存储到存储器中
$ D8 M# b0 c8 z @ LDMIA 加载多个字,并且在加载后自增基址寄存器
: P8 f# J3 P0 R T8 T( w STMIA 加载多个字,并且在加载后自增基址寄存器
( V/ u5 B2 d* N, \' [/ x PUSH 压入多个寄存器到栈中6 d* g$ _8 z. Q
POP 从栈中弹出多个值到寄存器中 f: L' G) I$ Y
16 位数据传送指令没有任何新内容,因为它们是 Thumb 指令,在 v4T 时就已经固定下来了。0 ~! A& e. q; `. \5 i& g8 n0 C5 L
$ A$ x. x6 z# X' I0 r
指令 功能
* B; z& \; B$ h2 _( x9 R SVC 系统服务调用
* D5 b/ M1 M: ]* e; W BKPT 断点指令。如果调试被使能,则进入调试状态(停机)。或者如果调试监视器异常被使能,则调用一个调试异常,否则调用一个 fault 异常
( a6 {& N8 m, K! | NOP 无操作
+ }, ]0 g" T1 @/ x5 a7 J& _1 l S CPSIE 使能 PRIMASK(CPSIE i)/FAULTMASK(CPSIE f)——清 0 相应的位9 q9 }0 Q* J. {* P; a. l
CPSID 除能 PRIMASK(CPSID i)/FAULTMASK(CPSID f)——置位相应的位5 L8 \- L9 O+ F4 w0 U
$ U" ]/ V6 B$ f) C; z5 C
表 4 其它 16 位指令3 S1 l9 ~5 G4 ] [1 n2 l% g
指令 功能/ C, h' ?. j" F( j+ Z
ADC 带进位加法* j/ h- e$ \9 Z# _5 M8 Z! }2 W
ADD 加法
; `& E9 A( E6 v) u ADDW 宽加法(可以加 12 位立即数)6 O% t9 I5 B3 A+ B- x2 t9 ]
AND 按位与
/ {9 i9 {7 m( l ASR 算术右移
# |! ]1 A7 w0 H3 @! W BIC 位清零(把一个数按位取反后,与另一个数逻辑与)
, T) [, k) o+ D- v4 n BFC 位段清零: R( q8 T8 m! ~4 G0 _! e: S
BFI 位段插入% I0 v* Z( L B8 u2 G
CMN 负向比较(把一个数和另一个数的二进制补码比较,并更新标志位)5 w; Q" e, N t; V* H6 Y: {/ T. \
CMP 比较两个数并更新标志位
3 |; O% i6 S, M/ x CLZ 计算前导零的数目
@' p, c3 q! u7 x
. H5 C: m3 H" t 表 5 32 位数据操作指令5 h" O: t+ a" N, M
, x2 m1 Y# F# N1 y* N2 N: j" w EOR 按位异或
) W) w4 q- x% j% }8 J% `( F( F LSL 逻辑左移5 n$ B+ h: s1 ]9 b. k. s
LSR 逻辑右移- W; \: g# y5 p
MLA 乘加8 _ Z8 C" u5 h9 {/ ]
MLS 乘减
; h& {; y$ D0 n" I* C MOVW 把 16 位立即数放到寄存器的底 16 位,高 16 位清 0: \5 i4 w7 |. S) N1 u3 b. ]) e I
MOV 加载 16 位立即数到寄存器(其实汇编器会产生 MOVW)
9 q! r" g5 Q5 [* a$ {$ Q8 H) g MOVT 把 16 位立即数放到寄存器的高 16 位,低 16 位不影响
+ a8 a0 R) k4 T$ k# a8 d0 P% Z/ P7 n MVN 移动一个数的补码
- E* X* M* C$ ]& f MUL 乘法
' P3 u- ]8 {1 O0 | ORR 按位或/ ~; v6 }% h# Q# p
ORN 把源操作数按位取反后,再执行按位或
4 t9 \8 a: O1 F) L& M RBIT 位反转(把一个 32 位整数先用 2 进制表达,再旋转 180 度)
( p& \9 _% P# c REV 对一个 32 位整数做按字节反转) I; ?% \5 N+ P% C
REVH/ 对一个 32 位整数的高低半字都执行字节反转& w# _0 g! ? p$ J' E& t0 |
REV16 对一个 32 位整数的低半字执行字节反转,再带符号扩展成 32 位数
" q! K0 I3 g/ P REVSH 圆圈右移# x5 f9 O8 f; ? v
ROR 带进位的逻辑右移一格(最高位用 C 填充,且不影响 C 的值). L3 z; Z1 j2 u. R
RRX 从一个 32 位整数中提取任意的位段,并且带符号扩展成 32 位整数( A9 o( l& o4 a, j& M/ u5 ]
SFBX 带符号除法7 B6 h- t t% E, |* k- Q
SDIV 带符号长乘加(两个带符号的 32 位整数相乘得到 64 位的带符号积,再把积+ B |( R+ L6 ~ J. _& U: W
SMLAL 加到另一个带符号 64 位整数中) ^) o% Q! S7 s# x V( E
SMULL 带符号长乘法(两个带符号的 32 位整数相乘得到 64 位的带符号积)
& X7 x, t7 }3 c4 Z SSAT 带符号的饱和运算6 R# D( m3 N0 {. d" ]8 p
SBC 带借位的减法* O- {3 `2 }$ T- L$ _: u1 K7 O" ^
SUB 减法
; g9 p2 J5 r- v# g5 B+ b5 t$ f5 y; X SUBW 宽减法,可以减 12 位立即数
# D0 S4 S# c+ ` SXTB 字节带符号扩展到 32 位数
8 t) i5 Q3 n9 E TEQ 测试是否相等(对两个数执行异或,更新标志但不存储结果)- x8 b6 Q2 G8 A- T" L
TST 测试(对两个数执行按位与,更新 Z 标志但不存储结果)
) k/ k x; j& ?7 Z) ?) N UBFX 无符号位段提取
6 r# [- u7 a1 {$ W( o4 s: j UDIV 无符号除法
& n8 c5 n. d3 w$ e5 X; g9 h UMLAL 无符号长乘加(两个无符号的 32 位整数相乘得到 64 位的无符号积,再把积加到另一个无符号 64 位整数中)
4 {, H1 ~/ K/ H6 d" o8 U: [ UMULL 无符号长乘法(两个无符号的 32 位整数相乘得到 64 位的无符号积)
' `" n& d0 X$ d; F USAT 无符号饱和操作(但是源操作数是带符号的)* D1 S7 p9 F7 D2 T. \. s
UXTB 字节被无符号扩展到 32 位(高 24 位清 0)# W1 R+ l9 P$ x" Z; q
UXTH 半字被无符号扩展到 32 位(高 16 位清 0)6 D" r( P6 D3 W' @* v: ~; F6 W- U
- Z% P! v" l; t1 ^% K7 r/ M! `. [7 b
表 6 32 位存储器数据传送指令
% T% t4 A) S- }5 S- m LDRH 加载半字到寄存器
/ O: d3 V) }7 f. U& B, A, q5 } LDRSH 加载半字到寄存器,再带符号扩展到 32 位
; u% O. d$ W m7 T5 V" [$ y: k LDM 从一片连续的地址空间中加载多个字到若干寄存器( z. W# d/ w# s4 g; P! s) a$ Z: K
LDRD 从连续的地址空间加载双字( 64 位整数)到 2 个寄存器) P2 Z/ T4 H- e* h$ |5 D" Z
STR 存储寄存器中的字. }8 Q# Z3 |. m& e- F
STRB 存储寄存器中的低字节
6 E; S* B6 [+ s: L% B STRH 存储寄存器中的低半字* |7 b' E# q9 p. \8 d9 C. |8 t
STM 存储若干寄存器中的字到一片连续的地址空间中
, ]0 z" k4 h% p STRD 存储 2 个寄存器组成的双字到连续的地址空间中0 f+ }" [" Z0 h% S3 M: k
PUSH 把若干寄存器的值压入堆栈中* \; U0 p& T" W3 v/ L
POP 从堆栈中弹出若干的寄存器的值
8 X+ O& i/ `8 x9 x% V/ F 表 7 32 位转移指令6 X* d6 ^" O$ F+ w
指令 功能
# i! B0 f8 N8 O" D3 b B 无条件转移+ p+ {# R5 L3 ^& U; }/ G
BL 转移并连接( 调用子程序) z. u5 R! B# I8 Q' Q! E _8 }4 s
TBB 以字节为单位的查表转移。从一个字节数组中选一个 8 位前向跳转地址并转移5 M! f' M6 A- f5 o; k
TBH 以半字为单位的查表转移。从一个半字数组中选一个 16 位前向跳转的地址并转移
) ?; b- m) ?& U* |" u p4 @5 a0 ? & d" K0 n) w' K
表 8 其它 32 位指令0 n9 y q; w. R# @+ W. F
指令 功能9 O G# q% R4 ]& n" _+ K5 K
LDREX 加载字到寄存器,并且在内核中标明一段地址进入了互斥访问状态
$ ~ e! u7 T( y1 H LDREXH 加载半字到寄存器,并且在内核中标明一段地址进入了互斥访问状态
4 I; r: x* S$ a; g' C7 U LDREXB 加载字节到寄存器,并且在内核中标明一段地址进入了互斥访问状态
! N. Y. |- h8 f) [4 T STREX 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字
- m7 y9 a) G: ~; ~) ] W- s% u STREXH 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的半字
: M5 P- k5 Z& s+ ]. X' u STREXB 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字节
& c* A7 D+ k- U1 X CLREX 在本地的处理上清除互斥访问状态的标记(先前由 LDREX/LDREXH/LDREXB 做的标记)
* ^9 t) v4 s! y2 R MRS 加载特殊功能寄存器的值到通用寄存器
) y- M: r6 ^9 u# h6 d- g MSR 存储通用寄存器的值到特殊功能寄存器
4 _ x3 r8 |! j9 M% N NOP 无操作; P- M( d s5 x
SEV 发送事件
/ U9 d+ L1 e8 R' w; a1 {* d E WFE 休眠并且在发生事件时被唤醒7 e4 {9 I) e$ P) n
WFI 休眠并且在发生中断时被唤醒
! _6 d& N, Z; Q& D ISB 指令同步隔离(与流水线和 MPU 等有关)8 I+ G9 z# B. Z: d. V# R: c* i7 _; X
DSB 数据同步隔离(与流水线、 MPU 和 cache 等有关) DMB 数据存储隔离(与流水线、 MPU 和 cache 等有关) $ U1 E& R6 C, G, U( r
: q1 b0 I$ T7 G; R, l, O- U
' ^( ?# Y, \. q8 V' C |
|