|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 行者~ABC 于 2021-1-7 10:05 编辑 6 t: Y' N8 X+ b. |4 p) S* K
* K; }; I5 k3 @: X7 C+ G
- g: x5 F1 e* A4 F: G7 e; ^, p4 u; ^5 \ARM Cortex-M4 支持的指令在下表 1~8 中列出。
+ A. X2 M7 s! p* b a6 F1 _
* @# `0 R& Z% Q' S7 i6 U 表 1 16 位数据操作指令7 j" l" ]; Z( v/ w! I- }4 T
指令 功能
) N& f# Q7 b% m$ X ADC 带进位加法
5 w; k: V' ]4 |$ N0 o ADD 加法% {: c& \) j( A
AND 按位与。这里的按位与和 C 的”&”功能相同
7 k5 i3 n6 H; A% j ASR 算术右移
* Z! V# p, f% T; o! F BIC 按位清 0(把一个数跟另一个无符号数的反码按位与)
/ E1 @8 l7 y" {2 q. j' l" o; u CMN 负向比较(把一个数跟另一个数据的二进制补码相比较)1 b+ i% t1 r- {/ A4 G& M8 N
CMP 比较(比较两个数并且更新标志)
7 i) \9 t5 n) |! A- Q+ \ CPY 把一个寄存器的值拷贝到另一个寄存器中! Z8 j4 S9 u; J) i
EOR 近位异或! T" }* w1 }: D+ s: l- p/ \
LSL 逻辑左移(如无其它说明,所有移位操作都可以一次移动多格)7 E! |! K8 w4 m4 [* b1 N8 p) v
LSR 逻辑右移6 f: U; R8 m6 h" z$ h2 K
MOV 寄存器加载数据,既能用于寄存器间的传输,也能用于加载立即数: }( i& J8 @1 G& |$ v1 F
MUL 乘法
3 A9 q+ u" F" P* [+ ^2 d) T' K4 e MVN 加载一个数的 NOT 值(取到逻辑反的值)
9 l& O; n: N: T! b" \: s2 c NEG 取二进制补码
2 t" ~5 B3 T# x+ T3 \2 E ORR 按位或
1 i8 B9 o4 ]7 S/ U& Y' c+ f7 c& L ROR 圆圈右移$ P9 z; ^8 w/ j8 Z
SBC 带借位的减法
1 g$ K1 q4 h' \- }$ e6 |" | SUB 减法
7 g& b4 f. G+ O8 t4 Z TST 测试(执行按位与操作,并且根据结果更新 Z)
: {% k) A0 Q# ~) @% ? [- l REV 在一个 32 位寄存器中反转字节序
, A9 a8 k5 m- n8 T4 T9 w' M- n s REVH 把一个 32 位寄存器分成两个 16 位数,在每个 16 位数中反转字节序! m1 J" x/ x, L* `+ q" P
REVSH 把一个 32 位寄存器的低 16 位半字进行字节反转,然后带符号扩展到 32 位3 h, n `& q$ A5 o; ~: |
SXTB 带符号扩展一个字节到 32 位2 d9 h6 p) x+ @' K
SXTH 带符号扩展一个半字到 32 位
; D. S* Y- ^2 F, G UXTB 无符号扩展一个字节到 32 位, R0 ?# u* Q+ X6 ?. l3 d. [
UXTH 无符号扩展一个半字到 32 位
7 I' k1 B$ K& T4 [ l3 K) ` 4 S+ `# c, y; _+ C' N# c+ O( ]
表 2 16 位转移指令
& s! E# _$ I: f6 ^ 指令 功能7 P' S9 p: A8 O/ {+ N0 r' ~
B 无条件转移
5 I3 c- K3 P- ^+ t4 {! H) q B<cond> 条件转移% }# j' W9 F( p7 A9 a7 W
BL 转移并链接。用于呼叫一个子程序,返回地址被存储在 LR 中
! _0 D; I3 C' i# l BLX 使用立即数的 BLX 不要在 ARM Cortex-M4 中使用( J+ ^/ X( \) `: d5 L J
CBZ 比较,如果结果为 0 就转移(只能跳到后面的指令)0 `6 |, n. f* ~5 f" ]; a
CBNZ 比较,如果结果非 0 就转移(只能跳到后面的指令): Q* m4 M& N8 F( @, i0 P
IT If‐Then w. k o( [$ m9 u, c
: N( n% ?- U' H* \) U; g
表 3 16 位存储器数据传送指令
; ~: R+ N$ ?6 D, q" F: z 指令 功能
- T, a! O+ h+ x$ C! x LDR 从存储器中加载字到一个寄存器中
- W) W* E; b- A) Q( c5 F: g LDRH 从存储器中加载半字到一个寄存器中
! T8 t; R$ Z0 \5 @3 |3 m LDRB 从存储器中加载字节到一个寄存器中/ \) N& N+ X, X/ t# D) k+ d
LDRSH 从存储器中加载半字,再经过带符号扩展后存储一个寄存器中, e2 @3 X, S7 u
LDRSB 从存储器中加载字节,再经过带符号扩展后存储一个寄存器中+ ]. V! T- w8 ?2 v6 G6 |- x. w
STR 把一个寄存器按字存储到存储器中: W# t$ L3 w! ?3 r
STRH 把一个寄存器存器的低半字存储到存储器中
% r7 L7 _! [$ \1 B4 Q0 w2 D STRB 把一个寄存器的低字节存储到存储器中) D( Q9 p/ ~( r" ] ]
LDMIA 加载多个字,并且在加载后自增基址寄存器2 S/ {/ L1 ?# }: e5 \
STMIA 加载多个字,并且在加载后自增基址寄存器. L1 p* x! i* r, b8 Q# ~4 R2 q. i
PUSH 压入多个寄存器到栈中: D3 I( {7 e& r
POP 从栈中弹出多个值到寄存器中
6 q; X- Z( L7 y7 l 16 位数据传送指令没有任何新内容,因为它们是 Thumb 指令,在 v4T 时就已经固定下来了。: g( B* {3 ?% Q+ e; f* L
: X2 X: y* h" ?: P- X' \8 b1 o 指令 功能) r* [- y r X. @* x6 ^6 j
SVC 系统服务调用
* S. d* E, N$ Y( i; m0 j BKPT 断点指令。如果调试被使能,则进入调试状态(停机)。或者如果调试监视器异常被使能,则调用一个调试异常,否则调用一个 fault 异常4 `' M' T" g. ?0 b# P7 ]
NOP 无操作( A9 T) F; A3 z" o3 s- V% j
CPSIE 使能 PRIMASK(CPSIE i)/FAULTMASK(CPSIE f)——清 0 相应的位
U, k% U! B; v! j, u2 x9 n+ J$ a CPSID 除能 PRIMASK(CPSID i)/FAULTMASK(CPSID f)——置位相应的位
4 H- g2 m: M U
8 X, J. G/ |, e3 Y/ d$ e: x 表 4 其它 16 位指令1 B1 Y: ]& D: U4 c5 q% F
指令 功能
) R1 X+ m# R0 Y* h, v* n ADC 带进位加法
+ d0 S' X) b1 O' m+ M ADD 加法& {! `/ A# L4 M
ADDW 宽加法(可以加 12 位立即数)
& T2 N9 K+ b c( S: r AND 按位与* G+ J8 j' Y5 `: K X
ASR 算术右移$ q9 q; [9 j" B' x1 ]) V8 L
BIC 位清零(把一个数按位取反后,与另一个数逻辑与)
}, \4 {5 w x BFC 位段清零
! n4 s7 H! l4 t' K5 d: h BFI 位段插入
3 W* E6 c8 a& z0 v# x CMN 负向比较(把一个数和另一个数的二进制补码比较,并更新标志位)
) Z! v! F3 T0 _ CMP 比较两个数并更新标志位
: _- c1 x: B. ^, b CLZ 计算前导零的数目
( F% Z# P( B! z$ m1 Q# t
$ U. T: {6 I: R9 L- o 表 5 32 位数据操作指令# P) x9 D+ q8 ?. ?# y$ x" x/ x3 f) |
( ^) L; @. H, ?0 P: Z
EOR 按位异或% |% f) f# g0 n
LSL 逻辑左移
& e2 v3 S" ]' R) L! ?" F: A3 L/ x LSR 逻辑右移
) y4 V( T; k, w MLA 乘加$ f6 t3 h3 ^; q( ]( [" N# y
MLS 乘减
1 D% {: N$ f0 M1 [+ m. O2 m4 X* r MOVW 把 16 位立即数放到寄存器的底 16 位,高 16 位清 07 \+ L" \8 i% p+ |/ R
MOV 加载 16 位立即数到寄存器(其实汇编器会产生 MOVW). o0 P0 c9 t# x5 S
MOVT 把 16 位立即数放到寄存器的高 16 位,低 16 位不影响
8 h' m5 t. x' O& P% n MVN 移动一个数的补码
1 O1 B# V: J+ C; B% v( f MUL 乘法7 q; o2 u* M0 v, }) s
ORR 按位或8 a6 a( J4 h# b. u* _( D1 t. Q) Q
ORN 把源操作数按位取反后,再执行按位或& w7 \" N& L7 z# o' K, Q. Q A
RBIT 位反转(把一个 32 位整数先用 2 进制表达,再旋转 180 度)
6 c. U0 o" c* F0 w* {& s" Y. a9 v6 M REV 对一个 32 位整数做按字节反转
5 ?' ]) W4 ~' V9 A8 T REVH/ 对一个 32 位整数的高低半字都执行字节反转& L* _: J0 m5 c7 i. N @ E
REV16 对一个 32 位整数的低半字执行字节反转,再带符号扩展成 32 位数
% ~7 V9 D- X$ |- b1 R% o) Y REVSH 圆圈右移
8 j7 X4 a2 Z+ z1 J5 I; [1 ^$ m5 G ROR 带进位的逻辑右移一格(最高位用 C 填充,且不影响 C 的值)
4 G9 x2 ^+ _' z& G# X RRX 从一个 32 位整数中提取任意的位段,并且带符号扩展成 32 位整数- L# \) Q% l' |" n( U
SFBX 带符号除法7 m( |3 q& P, I v" f ~: B
SDIV 带符号长乘加(两个带符号的 32 位整数相乘得到 64 位的带符号积,再把积
6 G% z2 g' |9 |' G" Y" V SMLAL 加到另一个带符号 64 位整数中)0 e+ t/ A3 G# n8 G
SMULL 带符号长乘法(两个带符号的 32 位整数相乘得到 64 位的带符号积)
! H7 c7 O0 l3 ^) @# I! U SSAT 带符号的饱和运算* B6 G6 c* ~8 v+ Q/ F
SBC 带借位的减法
: j4 X# G7 r: M W4 R9 F/ ~; l7 [ SUB 减法
0 X& C$ [* `& ^+ k/ t9 K7 w SUBW 宽减法,可以减 12 位立即数
- ]8 p! C d9 P% G C- N SXTB 字节带符号扩展到 32 位数
/ _6 z* u, T, i9 ?3 \: m3 k, h; R8 z TEQ 测试是否相等(对两个数执行异或,更新标志但不存储结果)3 R2 w0 p2 W* A+ K: i2 c
TST 测试(对两个数执行按位与,更新 Z 标志但不存储结果)
( ?8 J; }, `1 c; u. o7 Q5 ] UBFX 无符号位段提取 u5 z9 A8 F# R# ^0 `, a
UDIV 无符号除法
& }* i* X3 i% t" I/ T9 U UMLAL 无符号长乘加(两个无符号的 32 位整数相乘得到 64 位的无符号积,再把积加到另一个无符号 64 位整数中)
) n) b& ~; ^- M# X1 |5 { UMULL 无符号长乘法(两个无符号的 32 位整数相乘得到 64 位的无符号积)% M& K0 J5 I; p2 u$ d: j. }' i
USAT 无符号饱和操作(但是源操作数是带符号的)
% A3 `# Z! F* D* ?1 i UXTB 字节被无符号扩展到 32 位(高 24 位清 0)7 G8 H5 }; ]7 f$ I! p1 }
UXTH 半字被无符号扩展到 32 位(高 16 位清 0)3 D: F m* ?: b: m' d
% A0 ]" R# @" B; H/ ?/ s' h 表 6 32 位存储器数据传送指令/ _7 t* l- o2 f2 S$ f8 j- F8 H
LDRH 加载半字到寄存器# V+ n, z' P6 z* h
LDRSH 加载半字到寄存器,再带符号扩展到 32 位
- W6 k& g5 O! Z6 b$ {1 g LDM 从一片连续的地址空间中加载多个字到若干寄存器# G$ Q9 {8 |$ z+ x0 u
LDRD 从连续的地址空间加载双字( 64 位整数)到 2 个寄存器
! {/ ~7 [( Q( \. {3 u STR 存储寄存器中的字
4 t! V0 L- t$ o: }3 V STRB 存储寄存器中的低字节- r, J% a& h# X* a9 G
STRH 存储寄存器中的低半字
9 q! D. O+ r6 K) {5 m7 E& ~8 @ STM 存储若干寄存器中的字到一片连续的地址空间中
7 g8 s8 L; t, p9 K4 ~0 E1 y STRD 存储 2 个寄存器组成的双字到连续的地址空间中! J6 ?4 L# Q: v! b- Z/ t. o
PUSH 把若干寄存器的值压入堆栈中
g% t: c x: _2 r POP 从堆栈中弹出若干的寄存器的值
. t0 ~* m3 R" _ L3 K! T, A L 表 7 32 位转移指令
$ f$ C3 c+ w6 G' V: B 指令 功能 a9 a+ M) ]5 F. D
B 无条件转移
% E' x$ n% N* h) p$ U: T% `) X0 k; \ BL 转移并连接( 调用子程序)
$ H% X) `4 P& s TBB 以字节为单位的查表转移。从一个字节数组中选一个 8 位前向跳转地址并转移
% y; Y0 _ v( f7 f" G5 o TBH 以半字为单位的查表转移。从一个半字数组中选一个 16 位前向跳转的地址并转移" t: W$ y0 U6 A5 K+ ]- g
7 c8 I) I# E( O, t; v T. Q7 }6 x' B 表 8 其它 32 位指令( S7 q+ `# o5 t1 Q
指令 功能! P5 }7 G9 N) x N- a- h
LDREX 加载字到寄存器,并且在内核中标明一段地址进入了互斥访问状态( n1 D$ a- b/ S! n1 C6 u* U* d
LDREXH 加载半字到寄存器,并且在内核中标明一段地址进入了互斥访问状态
& o* G9 n5 U" Z! }; l LDREXB 加载字节到寄存器,并且在内核中标明一段地址进入了互斥访问状态
I8 C$ @6 E" l4 ]6 |4 A+ @ STREX 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字
+ E! Y. ]1 G1 m, u& C. c" s: _ P STREXH 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的半字/ V& [) V# {' L/ A
STREXB 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字节# G! k5 R4 a# j/ X% I" D6 o
CLREX 在本地的处理上清除互斥访问状态的标记(先前由 LDREX/LDREXH/LDREXB 做的标记)* I7 C$ {% c5 I; G& _
MRS 加载特殊功能寄存器的值到通用寄存器
e( p3 ~# v/ h* u MSR 存储通用寄存器的值到特殊功能寄存器" j) u0 g; P9 M
NOP 无操作' C% d; K: q0 D7 b9 b5 v
SEV 发送事件0 {+ t* z# N. n; Q
WFE 休眠并且在发生事件时被唤醒& f; w! D: M5 f; g/ K% u3 m
WFI 休眠并且在发生中断时被唤醒
1 V5 |. p2 t" Z ISB 指令同步隔离(与流水线和 MPU 等有关)9 h0 c, Y9 u c# G
DSB 数据同步隔离(与流水线、 MPU 和 cache 等有关) DMB 数据存储隔离(与流水线、 MPU 和 cache 等有关)
, p. ~& D$ f9 m; R3 }8 F2 H1 M* e5 F" P2 P' q+ D
# G+ I5 P z8 j/ s* M |
|