|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 行者~ABC 于 2020-11-16 15:59 编辑
$ P' s9 r* I0 K7 w' @" T' m( v% ~, `% Z2 O: S' V6 B+ E% T: N K; s
ARM Cortex-M4 支持的指令在下表 1~8 中列出。
% I3 A- f% b; w/ t# l. F2 o/ ]/ g/ V- V* P) }3 u; h1 e
表 1 16 位数据操作指令, d4 d" V2 Q" d- H; r) S3 _2 L' j- | X
指令 功能
k! E/ j U% e ADC 带进位加法) M' x( _6 J& _7 o6 U9 h
ADD 加法
& [5 g9 c0 O4 b( ?! n' L0 F7 @+ z AND 按位与。这里的按位与和 C 的”&”功能相同
8 f+ K* ^; [9 U: t g/ T8 e% }( W ASR 算术右移% g" ?7 y. r" o; E
BIC 按位清 0(把一个数跟另一个无符号数的反码按位与)
' q& N0 G3 V% |8 r& Y& h E& L! K* D5 W5 f CMN 负向比较(把一个数跟另一个数据的二进制补码相比较)
6 }7 ~9 Q- L; M CMP 比较(比较两个数并且更新标志)
D* \. w- c8 [$ r+ Z CPY 把一个寄存器的值拷贝到另一个寄存器中8 A& n3 O: c( d8 c/ R
EOR 近位异或
, P) E- \4 L7 Q- @8 y LSL 逻辑左移(如无其它说明,所有移位操作都可以一次移动多格)5 T7 I. s% q% N" r; s
LSR 逻辑右移
1 p1 o! k9 v% J9 @ MOV 寄存器加载数据,既能用于寄存器间的传输,也能用于加载立即数( B% z8 g, k7 `; f- f8 y3 `6 Z
MUL 乘法! C- t, `/ g# ~- D* X
MVN 加载一个数的 NOT 值(取到逻辑反的值)
8 m) r3 ]% @0 r" S- z- k2 [5 I NEG 取二进制补码! y, T' I% s7 W1 Q3 o2 [) \
ORR 按位或
8 F* S: \" w1 N- z G! U ROR 圆圈右移
3 r2 a& O! |% b" k5 }% h SBC 带借位的减法
! t2 x! [( ` |; ~9 F$ ]: U. c/ x SUB 减法
2 t% I; \8 A1 q/ S7 B/ y TST 测试(执行按位与操作,并且根据结果更新 Z); s6 m* Y( u5 t0 w- i" Q
REV 在一个 32 位寄存器中反转字节序
6 j8 _2 `( c2 }% U+ H4 ~4 o* [2 i% W REVH 把一个 32 位寄存器分成两个 16 位数,在每个 16 位数中反转字节序+ g/ G& |* z- r9 U. C, m
REVSH 把一个 32 位寄存器的低 16 位半字进行字节反转,然后带符号扩展到 32 位7 ^1 t3 o+ ~# k7 R9 c/ d8 ]# _
SXTB 带符号扩展一个字节到 32 位
, N; g& O- E5 N9 ]' e# I0 a# Y. f- K SXTH 带符号扩展一个半字到 32 位% \0 G# T1 H! {* O6 o4 v
UXTB 无符号扩展一个字节到 32 位1 ?6 `6 r% {3 O$ T" N" }, G
UXTH 无符号扩展一个半字到 32 位7 M+ {5 k1 ~* k* N
' s& d3 ~9 H# m' K- `2 x: e 表 2 16 位转移指令/ ?: v# O5 R9 \/ e) @
指令 功能 T1 j! | ?2 `4 C
B 无条件转移
/ g5 D+ X( V! c B<cond> 条件转移; W( n0 M' y, [% g
BL 转移并链接。用于呼叫一个子程序,返回地址被存储在 LR 中3 Y5 h3 [, S1 l! z
BLX 使用立即数的 BLX 不要在 ARM Cortex-M4 中使用0 ~3 ?/ D" p4 o1 R
CBZ 比较,如果结果为 0 就转移(只能跳到后面的指令); C* {, e( ^" P5 ^* \
CBNZ 比较,如果结果非 0 就转移(只能跳到后面的指令)1 w, a8 D7 j2 x: f- w# ~& ]
IT If‐Then, x7 i6 e; b' c+ @1 f
: ?0 m& b8 I: P) S6 f& P 表 3 16 位存储器数据传送指令
2 C! H2 E. G& k 指令 功能- x7 Z7 E2 E O- e6 w; S# f
LDR 从存储器中加载字到一个寄存器中. H% i7 Y7 P+ m+ D) R- r
LDRH 从存储器中加载半字到一个寄存器中
0 H' ~7 X! w! o! N& G9 ? LDRB 从存储器中加载字节到一个寄存器中
( k9 _; k* X+ ] LDRSH 从存储器中加载半字,再经过带符号扩展后存储一个寄存器中
9 Q- X( Y5 m4 B l8 L( y Y9 \6 [6 { LDRSB 从存储器中加载字节,再经过带符号扩展后存储一个寄存器中
" P* I' S6 J) ?4 I& p8 p STR 把一个寄存器按字存储到存储器中
7 Z% Y/ d3 U! D; | STRH 把一个寄存器存器的低半字存储到存储器中2 q- _1 _& g: V1 ?' `
STRB 把一个寄存器的低字节存储到存储器中& q, U/ ?* m; y1 x) d
LDMIA 加载多个字,并且在加载后自增基址寄存器6 }7 d! g4 U# o( }( n' T8 _
STMIA 加载多个字,并且在加载后自增基址寄存器
) H* V8 r) s' z/ \7 P0 P PUSH 压入多个寄存器到栈中" `$ J1 i8 \' I% h
POP 从栈中弹出多个值到寄存器中" G! V" v: l. W; U, q
16 位数据传送指令没有任何新内容,因为它们是 Thumb 指令,在 v4T 时就已经固定下来了。
; K$ X2 \5 l6 o8 b
$ V3 c- S5 P0 a0 C/ g3 e& x" E 指令 功能
4 T7 t; e1 h5 S9 a8 c SVC 系统服务调用
+ h2 o) P5 @4 @! _& c# P BKPT 断点指令。如果调试被使能,则进入调试状态(停机)。或者如果调试监视器异常被使能,则调用一个调试异常,否则调用一个 fault 异常
0 t9 Z% W+ b, b4 Q NOP 无操作
$ Y K4 \& P7 G# R9 c5 H5 V0 ~ CPSIE 使能 PRIMASK(CPSIE i)/FAULTMASK(CPSIE f)——清 0 相应的位
. ?$ c' A) M0 s- B) w5 B CPSID 除能 PRIMASK(CPSID i)/FAULTMASK(CPSID f)——置位相应的位8 C8 q8 O+ m2 I' q
. M; Y0 Y; r& S
表 4 其它 16 位指令2 E2 G3 Z0 ^* U2 e- h5 b3 r
指令 功能
8 {0 k3 l* ^. n( d- [& y8 \ ADC 带进位加法
* E8 o4 A# \( c6 \0 P4 d/ v ADD 加法' ^/ q( t$ A" c/ q
ADDW 宽加法(可以加 12 位立即数)
6 t/ P2 n+ l* n0 G" @6 j0 ~ AND 按位与
1 k; O- ^6 F: g. r9 A0 ~( v K ASR 算术右移
0 k* f* j( B) D( G' Z4 i* K" m BIC 位清零(把一个数按位取反后,与另一个数逻辑与)
6 u9 z0 l& l! ?2 \, I BFC 位段清零
; v) P E; U5 H& H D0 X2 g BFI 位段插入7 @' i# }3 Y5 o: o5 |0 P1 z6 Z* w; c
CMN 负向比较(把一个数和另一个数的二进制补码比较,并更新标志位)
1 _7 q8 e" q! N% D7 e/ Q& V7 z CMP 比较两个数并更新标志位' R- N6 M. c6 m7 O) ^
CLZ 计算前导零的数目) p' _, q+ l6 k3 i' v; ^
7 }3 ~ F9 G7 C: A 表 5 32 位数据操作指令
! ^; i* l8 m/ a- ] 9 _1 h' s1 U' U& ~
EOR 按位异或; P" i. D1 s J" [
LSL 逻辑左移
5 q7 r2 q5 h. w) G LSR 逻辑右移
1 }& a0 u, c3 R0 U4 ` MLA 乘加2 }' V1 s" c( X& m7 V1 X5 ]8 `) V9 i
MLS 乘减- v. `! n6 f2 y4 n
MOVW 把 16 位立即数放到寄存器的底 16 位,高 16 位清 0! v' H+ S: U, r% R4 J! ^- |! |
MOV 加载 16 位立即数到寄存器(其实汇编器会产生 MOVW)
; G4 q; m- _& ^; F" l7 L MOVT 把 16 位立即数放到寄存器的高 16 位,低 16 位不影响
( G* r* ]3 l) q. g, Y7 V MVN 移动一个数的补码
- S, |: ~8 p( m5 i1 M$ Z/ Y0 k MUL 乘法
1 [8 `; Y% q; S/ V8 w1 N. g; j2 |1 H ORR 按位或
$ M7 x: b. C( O+ H5 A+ d" F# P! [ ORN 把源操作数按位取反后,再执行按位或8 y) i& D( z9 _/ U6 H+ K
RBIT 位反转(把一个 32 位整数先用 2 进制表达,再旋转 180 度)3 `5 M. y5 L$ t& ]7 k8 {, a# ?
REV 对一个 32 位整数做按字节反转4 Y6 f8 G. C1 F! D/ A
REVH/ 对一个 32 位整数的高低半字都执行字节反转2 G/ n' w7 ~# u, o
REV16 对一个 32 位整数的低半字执行字节反转,再带符号扩展成 32 位数* I1 e: X) |5 Q+ Y
REVSH 圆圈右移* Y4 _% k3 ^# `% l3 y" e/ a
ROR 带进位的逻辑右移一格(最高位用 C 填充,且不影响 C 的值)
) } L, ?$ s( I6 i: m, b3 l RRX 从一个 32 位整数中提取任意的位段,并且带符号扩展成 32 位整数
( I; n9 A0 y. M) M0 ]" K SFBX 带符号除法
% b0 }& Q* t1 D6 k4 L2 M SDIV 带符号长乘加(两个带符号的 32 位整数相乘得到 64 位的带符号积,再把积
) ]: ?# o% o) R' y( A0 S SMLAL 加到另一个带符号 64 位整数中)4 m; Z/ \$ G k* n
SMULL 带符号长乘法(两个带符号的 32 位整数相乘得到 64 位的带符号积)
6 ~2 v6 g8 Z' O- l. w SSAT 带符号的饱和运算, b8 l1 x2 n( F2 F0 t1 ^- a
SBC 带借位的减法# G( U" p% p. S
SUB 减法6 L/ `8 J) Q' n
SUBW 宽减法,可以减 12 位立即数
6 g0 w+ D( X! P) R SXTB 字节带符号扩展到 32 位数: V. T h5 @7 Y- s4 ^# j) o
TEQ 测试是否相等(对两个数执行异或,更新标志但不存储结果)
, F+ e: M; D% ]9 F TST 测试(对两个数执行按位与,更新 Z 标志但不存储结果). `! B8 p" I# n- C! X
UBFX 无符号位段提取+ X& g% A& }$ c) T' t
UDIV 无符号除法
& Z1 R7 w" ?7 v% U6 R UMLAL 无符号长乘加(两个无符号的 32 位整数相乘得到 64 位的无符号积,再把积加到另一个无符号 64 位整数中)* _5 `9 f" Q$ i2 k4 U
UMULL 无符号长乘法(两个无符号的 32 位整数相乘得到 64 位的无符号积)
: ~- d0 I9 U# q% \- [5 \ USAT 无符号饱和操作(但是源操作数是带符号的)$ p9 O/ d) v) A. A2 T( t
UXTB 字节被无符号扩展到 32 位(高 24 位清 0): W. I6 K i- b3 I6 l* ^* P
UXTH 半字被无符号扩展到 32 位(高 16 位清 0)( B6 z: y, b2 C4 x
) {# x$ a: T3 t9 E
表 6 32 位存储器数据传送指令
4 y6 Q8 {+ L- |- ~- L# o, i: c LDRH 加载半字到寄存器
4 N6 W2 f* j. Q$ z. s LDRSH 加载半字到寄存器,再带符号扩展到 32 位7 I7 d0 i& V9 s9 E% f
LDM 从一片连续的地址空间中加载多个字到若干寄存器
1 K1 @8 u4 }7 o LDRD 从连续的地址空间加载双字( 64 位整数)到 2 个寄存器2 B5 Z i5 }8 ~" ~7 L
STR 存储寄存器中的字
8 R( v; Q8 N6 a4 S8 y: V4 ?; K STRB 存储寄存器中的低字节
& k) I0 S* b+ q1 ? STRH 存储寄存器中的低半字
* t1 e% v9 }3 ` STM 存储若干寄存器中的字到一片连续的地址空间中9 D. T4 n, f3 c, s) r8 Q2 @9 w
STRD 存储 2 个寄存器组成的双字到连续的地址空间中
+ r9 v q& Q9 E5 q1 w PUSH 把若干寄存器的值压入堆栈中' B0 ?( F" t( L0 k& e8 i# m
POP 从堆栈中弹出若干的寄存器的值
/ F: c7 k7 b+ Q+ n5 w 表 7 32 位转移指令
9 H5 S4 L: b) f1 ~ 指令 功能% M& O/ @# s: c0 x. @* X( M
B 无条件转移# f6 I- [) s0 P
BL 转移并连接( 调用子程序)
0 _! p [4 r6 A- m TBB 以字节为单位的查表转移。从一个字节数组中选一个 8 位前向跳转地址并转移
- O6 _! T: T4 F) n+ F TBH 以半字为单位的查表转移。从一个半字数组中选一个 16 位前向跳转的地址并转移
7 E4 _% [2 m2 B) W
5 n: @6 _9 k @ 表 8 其它 32 位指令
9 p# V" h: [6 A" q 指令 功能
; i! @3 g* x3 D LDREX 加载字到寄存器,并且在内核中标明一段地址进入了互斥访问状态/ R% j2 m( V; a% c$ g
LDREXH 加载半字到寄存器,并且在内核中标明一段地址进入了互斥访问状态
% [2 u1 A7 V' f. V0 w4 A LDREXB 加载字节到寄存器,并且在内核中标明一段地址进入了互斥访问状态
& H7 C% Y- s' r5 u7 m5 a% I STREX 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字* Q Z- V/ V# z6 O1 s" h7 c6 {
STREXH 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的半字
5 u* c" O! C' i7 C1 ~ STREXB 检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字节+ E; y m$ Q/ c2 m! M/ c
CLREX 在本地的处理上清除互斥访问状态的标记(先前由 LDREX/LDREXH/LDREXB 做的标记)
]! f% X) z7 H MRS 加载特殊功能寄存器的值到通用寄存器
9 B# P" g& n; [5 t+ |* h2 Z MSR 存储通用寄存器的值到特殊功能寄存器9 z0 T! D: v8 i8 J, y! M, f
NOP 无操作
* t1 F5 e6 I5 v W' z: \2 F SEV 发送事件
: b3 l; C, z+ q. ]9 g! r WFE 休眠并且在发生事件时被唤醒
& S5 K, |7 A1 Y; a% E! n, @( y WFI 休眠并且在发生中断时被唤醒1 j8 j0 J8 j2 A& Y$ z
ISB 指令同步隔离(与流水线和 MPU 等有关)( d) X( t! L. b2 g; U( W
DSB 数据同步隔离(与流水线、 MPU 和 cache 等有关) DMB 数据存储隔离(与流水线、 MPU 和 cache 等有关) . D' y& R- `5 L9 r3 S7 O
' B, u8 E& S& d% }4 z) M# ^7 o3 _+ C! y( N: H* [) u1 x
|
|