Cortex-M4内核参考手册笔记-STM32 Cortex-M4 指令集

 

3.1 指令集概述

本处理器实现Thumb指令集版本。表21列出了支持的指令。

表21中:

  • 尖括号<>表示操作数的可选形式

  • 花括号{}表示可选操作数

  • 操作数列未穷举所有形式

  • Op2是灵活的第二操作数,可以是寄存器或常量

  • 多数指令可使用可选的条件码后缀

更多指令和操作数信息,请参阅指令详细描述。

 

 

 

 

 

 

 

 

3.2 CMSIS 内联函数

ISO/IEC C代码无法直接访问某些Cortex-M4指令。本节描述由CMSIS提供的、可生成这些指令的内联函数,这些函数也可能由C编译器提供。若C编译器不支持相应的内联函数,则可能需要使用内联汇编来访问特定指令。

CMSIS提供了表22所列的内联函数,用于生成ANSI C无法直接访问的指令。

表22. 用于生成Cortex-M4指令的CMSIS内联函数

 

CMSIS还提供了一系列通过MRS和MSR指令访问特殊寄存器的函数(见表23)。

表23. 用于访问特殊寄存器的CMSIS内联函数

 

3.3 关于指令描述

 

3.3.1 操作数

指令操作数可以是Arm寄存器、常量或其他指令特定参数。指令对操作数执行操作后,通常将结果存储于目标寄存器中。若指令包含目标寄存器,该寄存器通常列在操作数之前。

部分指令的操作数具有灵活性,既可以是寄存器也可以是常量(参见"灵活的第二操作数")。

3.3.2 使用 PC 或 SP 时的限制

多数指令对程序计数器(PC)或堆栈指针(SP)能否作为操作数或目标寄存器存在限制。具体限制请参阅各指令描述。

通过BX、BLX、LDM、LDR或POP指令写入PC的地址必须满足bit[0]=1以确保正确执行,因为该位指示所需的指令集,而Cortex-M4处理器仅支持Thumb指令集。

3.3.3 灵活的第二操作数

许多通用数据处理指令具有灵活的第二操作数,在指令语法描述中显示为operand2。

operand2可以是:

  • 常量

  • 寄存器(可选带移位操作)

常量形式

操作数2的常量需以#constant形式指定,其中constant可为以下任意类型:

  • 通过8位值左移任意位数生成的32位字常量

  • 0x00XY00XY形式的常量

  • 0xXY00XY00形式的常量

  • 0xXYYXYXY形式的常量
    (上述常量中X和Y代表十六进制数字)

少数指令支持更广范围的常量值,具体参见各指令独立描述。

当MOVS、MVNS、ANDS、ORRS、ORNS、EORS、BICS、TEQ或TST指令使用操作数2常量时:

  • 若常量值>255且可由8位值移位产生,则进位标志(C)将更新为该常量bit[31]的值

  • 其他类型常量不影响进位标志

指令替换机制
若指定非法常量,汇编器可能生成等效指令。例如:
CMP Rd, #0xFFFFFFFE 可能被替换为等效的 CMN Rd, #0x2

寄存器带可选移位
操作数2寄存器格式为Rm (, shift),其中:

  • Rm:存储第二操作数的寄存器

  • Shift:可选移位操作(未指定时等效于LSL #0),支持以下类型:
    ASR #n:算术右移n位(1≤n≤32)
    LSL #n:逻辑左移n位(1≤n≤31)
    LSR #n:逻辑右移n位(1≤n≤32)
    ROR #n:循环右移n位(1≤n≤31)
    RRX:带扩展的单次循环右移

     ——:若省略移位操作,则默认为LSL #0(不进行移位)

当省略移位操作或指定LSL #0时,指令将直接使用Rm寄存器中的值。

若指定移位操作:

    1. 系统会对Rm值进行移位处理,生成32位结果供指令使用

    2. 原Rm寄存器中的值保持不变

    3. 特定指令执行带移位的寄存器操作时,会更新进位标志位(C)
      (移位操作对标志位的影响详见《移位操作》章节)

3.3.4 移位操作

 

寄存器移位操作将寄存器中的位向左或向右移动指定的位数(即移位长度)。寄存器移位可通过以下方式执行:

  • 直接指令:ASR、LSR、LSL、ROR和RRX指令直接执行移位操作,结果写入目标寄存器。

  • 操作数2的计算:在指定第二个操作数为带移位的寄存器时(参见第60页的灵活第二操作数),移位结果由指令使用。

允许的移位长度取决于移位类型和指令(详见各指令说明或灵活第二操作数)。若移位长度为0,则不进行移位。寄存器移位操作会更新进位标志,除非移位长度为0。以下小节描述了各种移位操作及其对进位标志的影响。在描述中,Rm是待移位的寄存器,*n*为移位长度。

ASR

算术右移*n*位将Rm寄存器的左起32-*n*位向右移动*n*位,存入结果的右起32-*n*位,同时将寄存器的原始bit[31]复制到结果的左起*n*位(参见第62页的图13:ASR #3)。

ASR #n操作可用于将Rm寄存器中的值除以2n2n,结果向负无穷方向取整。

当指令为ASRS,或在MOVS、MVNS、ANDS、ORRS、ORNS、EORS、BICS、TEO或TST指令中作为operand2使用ASR #n时,进位标志会更新为Rm寄存器移出的最后一位(bit[n-1])。

注意:

  1. 若*n*大于或等于32,则结果的所有位均设置为Rm的bit[31]值。

  2. 若*n*大于或等于32且更新了进位标志,则进位标志更新为Rm的bit[31]值。

 

LSR

逻辑右移 nn 位将 RmRm 寄存器的左起 32-nn 位向右移动 nn 位,存入结果的右起 32-nn 位,同时将结果的左起 nn 位设置为 0(见图 14)。

LSR #n 操作可用于将 RmRm 寄存器中的值除以 2n2n(前提是该值被视为无符号整数)。

当指令为 LSRS,或在 MOVS、MVNS、ANDS、ORRS、ORNS、EORS、BICS、TEQ 或 TST 指令中作为 operand2 使用 LSR #n 时,进位标志会更新为 RmRm 寄存器移出的最后一位(bit[n−1n1])。

注意:

  1. 若 nn 大于或等于 32,则结果的所有位均清零为 0。

  2. 若 nn 大于或等于 33 且更新了进位标志,则进位标志更新为 0。

 

LSL

逻辑左移 nn 位将 RmRm 寄存器的右起 32-nn 位向左移动 nn 位,存入结果的左起 32-nn 位,同时将结果的右起 nn 位设置为 0(见图 15. LSL #3)。

LSL #n 操作可用于将 RmRm 寄存器中的值乘以 2n2n(无论该值被视为无符号整数还是二进制补码有符号整数)。溢出可能无警告。

当指令为 LSLS,或在 MOVS、MVNS、ANDS、ORRS、ORNS、EORS、BICS、TEQ 或 TST 指令中作为 operand2 使用非零 nn 的 LSL #n 时,进位标志会更新为 RmRm 寄存器移出的最后一位(bit[32−n32n])。若使用 LSL #0,这些指令不会影响进位标志。

注意:

  1. 若 nn 大于或等于 32,则结果的所有位均清零为 0。

  2. 若 nn 大于或等于 33 且更新了进位标志,则进位标志更新为 0。

ROR

右循环移位 nn 位将 Rm 寄存器的左起 32-nn 位向右移动 nn 位,存入结果的右起 32-nn 位,同时将寄存器的右起 nn 位循环移至结果的左起 nn 位(见图 16)。

当指令为 RORS,或在 MOVS、MVNS、ANDS、ORRS、ORNS、EORS、BICS、TEQ 或 TST 指令中作为 operand2 使用 ROR #nn 时,进位标志会更新为 Rm 寄存器循环移出的最后一位(bit[nn-1])。

注意:

  1. 若 nn 为 32,则结果值与 Rm 中的值相同;若更新了进位标志,则进位标志更新为 Rm 的 bit[31]。

  2. 当移位长度 nn 大于 32 时,ROR 操作等效于移位长度为 nn-32 的 ROR。

 

RRX

带扩展的右循环移位将 Rm 寄存器的所有位向右移动 1 位,并将进位标志的值复制到结果的 bit[31](见图 17)。

当指令为 RRXS,或在 MOVS、MVNS、ANDS、ORRS、ORNS、EORS、BICS、TEG 或 TST 指令中作为 operand2 使用 RRX 时,进位标志会更新为 Rm 寄存器的 bit[0]。

3.3.5 地址对齐

 

对齐访问是指:对于字(word)、双字(dual word)或多字(multiple word)访问使用字对齐地址,或对于半字(halfword)访问使用半字对齐地址。字节(byte)访问始终是对齐的。

Cortex-M4处理器仅支持以下指令的非对齐访问:

  • LDR, LDRT

  • LDRH, LDRHT

  • LDRSH, LDRSHT

  • STR, STRT

  • STRH, STRHT

其他所有加载和存储指令若执行非对齐访问都会触发用法错误异常,因此这些指令的访问必须地址对齐。有关用法错误的更多信息,请参阅第44页的错误处理

非对齐访问通常比对齐访问更慢。此外,某些内存区域可能不支持非对齐访问。因此,Arm建议程序员确保访问是对齐的。为避免意外产生非对齐访问,可使用配置和控制寄存器中的UNAUGN_TRP位来捕获所有非对齐访问,详见第231页的配置和控制寄存器(CCR)

3.3.6 PC 相对寻址表达式

PC相对表达式(或称标签)是表示指令或字面数据地址的符号。在指令中,它表示为PC值加上或减去一个数字偏移量。汇编器根据标签和当前指令地址计算所需的偏移量。若偏移量过大,汇编器将报错。

  • 对于B、BL、CBNZ和CBZ指令,PC值为当前指令地址加4字节。

  • 对于其他使用标签的指令,PC值为当前指令地址加4字节,并将结果的bit[1]清零以确保字对齐。

  • 某些汇编器可能支持其他PC相对表达式语法,例如标签加减数字,或[PC, #number]形式的表达式。

3.3.7 条件执行

大多数数据处理指令可选择根据操作结果更新应用程序状态寄存器(APSR)中的条件标志(见第21页的应用程序状态寄存器)。部分指令更新所有标志,部分仅更新子集。若标志未被更新,则保留原值。各指令影响的标志详见其描述。

可根据其他指令设置的条件标志来条件执行指令:

    • 在更新标志的指令之后立即执行

    • 在任意数量未更新标志的中间指令之后执行

可通过两种方式实现条件执行:使用条件分支指令,或在指令后添加条件码后缀(完整后缀列表参见第67页表24:条件码后缀)。条件码后缀使处理器能够基于标志位测试条件。若条件测试失败,该指令将:

  • 不执行

  • 不写入目标寄存器

  • 不影响任何标志位

  • 不触发任何异常

除条件分支指令外,所有条件指令必须位于IT指令块内(相关限制详见第145页IT指令说明)。部分汇编器在检测到IT块外的条件指令时可能自动插入IT指令。

CBZ和CBNZ指令可用于将寄存器值与零比较并根据结果跳转。

本节包含:

  • 条件标志说明

  • 条件码后缀(第67页)

条件标志说明

APSR包含以下条件标志位:

  • N(负标志):运算结果为负时置1,否则清零

  • Z(零标志):运算结果为零时置1,否则清零

  • C(进位标志):下列情况置1,否则清零

  • V  :当操作导致溢出时置1,否则清0。

有关APSR的更多信息,请参阅第19页的程序状态寄存器

以下情况会产生进位(Carry):

  • 加法结果大于或等于232232时。

  • 减法结果为正数或零时。

  • 在移动或逻辑指令中,内联桶形移位器操作产生的结果。

以下情况会发生溢出(Overflow):

  • 如果两个负数相加结果为正数。

  • 如果两个正数相加结果为负数。

  • 如果从一个负数中减去一个正数得到正数结果。

  • 如果从一个正数中减去一个负数得到负数结果。

比较操作(Compare)与减法(CMP)或加法(CMN)操作相同,只是结果会被丢弃。更多信息请参阅指令描述。

大多数指令仅在指定S后缀时更新状态标志。更多信息请参阅指令描述。

条件码后缀

可条件执行的指令拥有一个可选的条件码,在语法描述中表示为{cond}。条件执行需要前置的IT指令。只有当APSR中的条件码标志满足指定条件时,带有条件码的指令才会执行。_表24_列出了可用的条件码。

通过结合IT指令使用条件执行,可以减少代码中的分支指令数量。

_表24_还展示了条件码后缀与N、Z、C、V标志之间的关系。

 

表24. 条件码后缀

后缀标志条件含义
EQ Z=1Z=1 相等
NE Z=0Z=0 不相等
CS或HS C=1C=1 无符号大于或等于(≥)
CC或LO C=0C=0 无符号小于(<)
MI N=1N=1 负数
PL N=0N=0 正数或零
VS V=1V=1 溢出
VC V=0V=0 无溢出
HI C=1C=1且Z=0Z=0 无符号大于(>)
LS C=0C=0或Z=1Z=1 无符号小于或等于(≤)
GE N=VN=V 有符号大于或等于(≥)
LT N≠VN=V 有符号小于(<)
GT Z=0Z=0且N=VN=V 有符号大于(>)
LE Z=1Z=1且N≠VN=V 有符号小于或等于(≤)
AL 任意值 无条件执行(默认无后缀时使用)

_具体示例1:绝对值_展示了如何使用条件指令计算一个数的绝对值。R0 = ABS(R1)。

具体示例1:绝对值

MOVS R0, R1      ; R0 = R1,并设置标志位  
IT MI            ; 为负数条件配置IT指令  
RSBMI R0, R1, #0 ; 若为负数,R0 = -R1  

_具体示例2:比较并更新值_展示了如何通过条件指令在R0和R2分别有符号大于R1和R3时更新R4的值。

具体示例2:比较并更新值

3.3.8 指令宽度选择

许多指令可以根据指定的操作数和目标寄存器生成16位或32位编码。对于其中部分指令,您可以通过使用指令宽度后缀强制指定指令大小。

  • .W后缀强制生成32位指令编码

  • .N后缀强制生成16位指令编码

若指定了指令宽度后缀但汇编器无法生成对应宽度的指令编码,将报错。

某些情况下必须显式指定.W后缀,例如当操作数是某条指令的标签或字面量数据时(如分支指令)。这是因为汇编器可能无法自动生成正确大小的编码。

使用指令宽度后缀时,需将其紧跟在指令助记符和条件码(如有)之后。
_具体示例3:指令宽度选择_展示了带宽度后缀的指令用法。

具体示例3:指令宽度选择

BCS.W label      ; 即使短跳转也强制生成32位指令  
ADDS.W R0, R0, R1 ; 即使可用16位指令也强制生成32位指令  

3.4 存储器访问指令

表25展示了内存访问指令:

 

助记符简要描述参考位置
ADR 加载PC相对地址 第70页 ADR指令
CLREX 清除独占标记 第80页 CLREX指令
LDM(mode) 加载多寄存器 第76页 LDM和STM指令
LDR(type) 立即数偏移加载寄存器 第71页 LDR和STR(立即数偏移)
LDR(type) 寄存器偏移加载寄存器 第73页 LDR和STR(寄存器偏移)
LDR(type)T 非特权模式加载寄存器 第74页 LDR和STR(非特权访问)
LDR PC相对地址加载寄存器 第75页 LDR(PC相对)
LDRD 双寄存器加载 第71页 LDR和STR(立即数偏移)
LDREX(type) 独占加载寄存器 第79页 LDREX和STREX指令
POP 从栈中弹出寄存器 第78页 PUSH和POP指令
PUSH 将寄存器压入栈 第78页 PUSH和POP指令
STM(mode) 存储多寄存器 第76页 LDM和STM指令
STR(type) 立即数偏移存储寄存器 第71页 LDR和STR(立即数偏移)
STR(type) 寄存器偏移存储寄存器 第73页 LDR和STR(寄存器偏移)
STR(type)T 非特权模式存储寄存器 第74页 LDR和STR(非特权访问)
STREX(type) 独占存储寄存器 第79页 LDREX和STREX指令

3.4.1 ADR(地址加载)

加载PC相对地址

语法

ADR{cond} Rd, label

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • label:PC相对表达式(参见第65页"PC相对表达式")

操作原理

ADR通过将立即数值与PC值相加来计算地址,并将结果写入目标寄存器。

由于采用PC相对寻址,ADR生成的代码具有位置无关性。

若使用ADR生成BX或BLX指令的目标地址,必须确保生成地址的bit[0]置1以保证正确执行。

label的取值范围必须为PC值±4095范围内。

注意:
如需获取最大偏移范围或生成非字对齐地址,可能需要使用.W后缀(参见第68页"指令宽度选择")。

限制条件

目标寄存器Rd不能是SP或PC。

状态标志

本指令不改变任何状态标志。

示例

ADR R1, TextMessage  ; 将标签TextMessage的地址值写入R1

3.4.2 LDR 和 STR(立即数偏移)

支持立即数偏移、前变址立即数偏移和后变址立即数偏移的加载/存储操作

语法

op{type}{cond} Rt, [Rn {, #offset}]    ; 立即数偏移
op{type}{cond} Rt, [Rn, #offset]!      ; 前变址  
op{type}{cond} Rt, [Rn], #offset       ; 后变址  
opD{cond} Rt, Rt2, [Rn {, #offset}]    ; 双字立即数偏移  
opD{cond} Rt, Rt2, [Rn, #offset]!      ; 双字前变址  
opD{cond} Rt, Rt2, [Rn], #offset       ; 双字后变址  

参数说明:

  • op:LDR(加载寄存器)或STR(存储寄存器)

  • type:

    • B:无符号字节(加载时零扩展至32位)

    • SB:有符号字节(仅LDR,符号扩展至32位)

    • H:无符号半字(加载时零扩展至32位)

    • SH:有符号半字(仅LDR,符号扩展至32位)

    • --:省略时表示字操作

  • cond:可选条件码(参见第65页"条件执行")

  • Rt:待加载/存储的寄存器

  • Rn:基址寄存器

  • offset:相对于Rn的偏移量(省略时直接使用Rn的值作为地址)

  • Rt2:双字操作时的附加寄存器

操作原理

LDR指令从内存加载数据到1-2个寄存器,STR指令将1-2个寄存器的值存储到内存。

立即数偏移的加载/存储指令支持以下寻址模式:

    1. 偏移寻址
      将偏移量与Rn中的地址相加/相减后作为访问地址,Rn值不变。
      语法格式:[Rn, #offset]

    2. 前变址寻址
      先计算偏移量后的地址用于访问,再将结果写回Rn。
      语法格式:[Rn, #offset]!

    3. 后变址寻址
      直接使用Rn值作为访问地址,操作后再将偏移量后的地址写回Rn。
      语法格式:[Rn], #offset

 

可加载/存储的数据类型包括:字节、半字、字或双字。字节和半字可支持有符号或无符号格式(参见第65页地址对齐说明)。

*表26列出了立即数偏移、前变址和后变址形式的偏移量范围。

限制条件

  • 加载指令(LDR):

    • 仅当字加载时,Rt可为SP或PC

    • 双字加载时,Rt必须不同于R12

    • 前变址/后变址模式下,Rn必须不同于R1R12

  • 当PC作为字加载目标时:

    • 加载值的bit[0]必须为1以确保正确执行

    • 程序会跳转至bit[0]置0后的地址

    • 若为条件指令,必须作为IT块的最后一条指令

  • 存储指令(STR):

    • 仅当字存储时,Rt可为SP

    • Rt不可为PC

    • Rn不可为PC

    • 前变址/后变址模式下,Rn必须不同于R1R12

状态标志
这些指令不会改变任何状态标志。

示例

 
LDR R8, [R10]              ; 将R10指向的地址内容加载到R8
LDRNE R2, [R5, #960]       ; (条件执行)将R5+960地址的字数据加载到R2
                           ; 并将R5值增加960
STR R2, [R9, #const-struct]; const-struct为取值0-4095的常数表达式
                           ; 将R2存储到R9+const-struct地址
STRH R3, [R4], #4          ; 将R3作为半字存入R4指向地址,随后R4+=4
LDRD R8, R9, [R3, #0x20]!  ; 从R3+0x20加载双字到R8/R9,并更新R3值
STRD R0, R1, [R8], #-16    ; 将R0/R1双字存入R8/R8+4地址,随后R8-=16

3.4.3 LDR 和 STR(寄存器偏移)

基于寄存器的加载与存储

语法

其中:

  • op:可以是LDR(加载寄存器)或STR(存储寄存器)。

  • type:可选以下类型之一:

    • B:无符号字节,加载时零扩展至32位。

    • SB:有符号字节,加载时符号扩展至32位(仅LDR支持)。

    • H:无符号半字,加载时零扩展至32位。

    • SH:有符号半字,加载时符号扩展至32位(仅LDR支持)。

    • --:省略,表示字(word)。

  • cond:可选条件码,参见第65页的“条件执行”。

  • Rt:待加载或存储的寄存器。

  • Rn:基址寄存器,内存地址基于此寄存器。

  • Rm:包含偏移值的寄存器。

  • LSL #n:可选移位操作,n取值范围为0到3。

操作
LDR指令从内存加载值到寄存器,STR指令将寄存器值存储到内存。内存地址为基址寄存器Rn加上偏移值(由Rm指定,并可选择左移最多3位)。加载或存储的值可以是字节、半字或字。对于加载指令,字节和半字可支持有符号或无符号扩展(参见第65页的“地址对齐”)。

限制

  • Rn不能为PC。

  • Rm不能是SP或PC。

  • Rt仅在字加载和字存储时可为SP。

  • Rt仅在字加载时可为PC。

当Rt为PC且执行字加载时:

  • 加载值的bit[0]必须为1以确保正确执行,程序会跳转到该半字对齐的地址。

  • 若指令为条件指令,则必须是IT块中的最后一条指令。

条件标志位
这些指令不会改变标志位。

示例

 

3.4.4 LDR 和 STR(非特权模式)

 支持非特权模式的加载与存储

语法

其中:

  • op:可以是LDR(加载寄存器)或STR(存储寄存器)。

  • type:可选以下类型之一:

    • B:无符号字节,加载时零扩展至32位。

    • SB:有符号字节,加载时符号扩展至32位(仅LDR支持)。

    • H:无符号半字,加载时零扩展至32位。

    • SH:有符号半字,加载时符号扩展至32位(仅LDR支持)。

    • --:省略,表示字(word)。

  • cond:可选条件码,参见第65页的“条件执行”。

  • Rt:待加载或存储的寄存器。

  • Rn:基址寄存器,内存地址基于此寄存器。

  • offset:相对于Rn的偏移量,取值范围为0到255。若省略,则地址为Rn中的值。

操作
这些加载与存储指令的功能与“立即数偏移的LDR和STR指令”(参见第71页)相同,区别在于:即使运行在特权模式下,这些指令也仅以非特权权限访问内存。
在非特权模式下,这些指令的行为与普通立即数偏移的内存访问指令完全一致。

限制

  • Rn不能为PC。

  • Rt不能是SP或PC。

条件标志位
这些指令不会改变标志位。

示例

3.4.5 LDR(PC 相对寻址)

从内存加载寄存器(基于PC的地址)

语法

其中:

  • type:可选以下类型之一:

    • B:无符号字节,零扩展至32位。

    • SB:有符号字节,符号扩展至32位。

    • H:无符号半字,零扩展至32位(注:原文误写为“sign extends”,应为“zero extends”)。

    • SH:有符号半字,符号扩展至32位。

    • --:省略,表示字(word)。

  • cond:可选条件码,参见第65页的“条件执行”。

  • Rt:目标寄存器(加载值存放位置)。

  • Rt2:第二目标寄存器(仅LDRD指令使用)。

  • label:PC相对地址表达式(参见第65页的“PC相对表达式”)。

操作
LDR指令从PC相对寻址的内存地址加载值到寄存器。内存地址由标签或相对于PC的偏移量指定。可加载的值为字节、半字或字,且支持有符号/无符号扩展(参见第65页的“地址对齐”)。

标签范围限制

  • 单字/半字/字节加载:标签与PC的偏移范围为 -4095至4095。

  • 双字加载(LDRD):标签与PC的偏移范围为 -1020至1020。
    若超出默认范围,需使用.W后缀扩展偏移量(参见第68页的“指令宽度选择”)。

限制

  • Rt2不能为SP或PC。

  • Rt必须与Rt2不同。

  • Rt仅在字加载时可为SP或PC。

  • 当Rt为PC且执行字加载时:

    • 加载值的bit[0]必须为1以确保正确执行,程序会跳转到该半字对齐的地址。

    • 若指令为条件指令,则必须是IT块中的最后一条指令。

条件标志位
这些指令不会改变标志位。

示例

LDR R0, LookUpTable     ; 从标签为LookUpTable的地址加载一个字数据到R0  
LDRSB R7, localdata     ; 从标签为localdata的地址加载一个字节值,符号扩展为字后存入R7  

3.4.6 LDM 和 STM(多寄存器加载/存储)

多寄存器加载与存储

语法

其中:

  • op:可以是LDM(加载多寄存器)或STM(存储多寄存器)。

  • addr_mode:寻址模式,可选以下之一:

    • IA:每次访问后递增地址(默认模式)。

    • DB:每次访问前递减地址。

  • cond:可选条件码,参见第65页的“条件执行”。

  • Rn:基址寄存器,内存地址基于此寄存器。

  • !:可选回写后缀。若存在,最终访问的地址将写回Rn。

  • reglist:待加载或存储的寄存器列表,用大括号包围,可包含寄存器范围(多个寄存器或范围需用逗号分隔,参见第77页示例)。

指令别名

  • LDM、LDMFD 是 LDMIA 的同义词。LDMFD表示用于从满递减栈弹出数据。

  • LDMEA 是 LDMDB 的同义词,表示用于从空递增栈弹出数据。

  • STM、STMEA 是 STMIA 的同义词。STMEA表示用于向空递增栈压入数据。

  • STMFD 是 STMDB 的同义词,表示用于向满递减栈压入数据。

操作

  • LDM指令:从基于Rn的内存地址加载字数据到reglist中的寄存器。

  • STM指令:将reglist中寄存器的字数据存储到基于Rn的内存地址。

对于LDM、LDMIA、LDMFD、STM、STMIA和STMEA指令,访问的内存地址以4字节为间隔,范围从RnRn到Rn+4∗(n−1)Rn+4(n1),其中nn是寄存器列表_reglist_中的寄存器数量。访问按寄存器编号的升序进行,编号最小的寄存器使用最低的内存地址,编号最大的寄存器使用最高的内存地址。如果指定了写回后缀,则将Rn+4∗(n−1)Rn+4(n1)的值写回RnRn。

对于LDMDB、LDMEA、STMDB和STMFD指令,访问的内存地址以4字节为间隔,范围从RnRn到Rn−4∗(n−1)Rn4(n1),其中nn是寄存器列表_reglist_中的寄存器数量。访问按寄存器编号的降序进行,编号最大的寄存器使用最高的内存地址,编号最小的寄存器使用最低的内存地址。如果指定了写回后缀,则将Rn−4∗(n)Rn4(n)的值写回RnRn。

PUSH和POP指令可以用这种形式表示(详见_PUSH和POP_部分)。

限制条件

在这些指令中:

  • _Rn不能是PC。

  • _reglist不能包含SP。

  • 在任何STM指令中,_reglist不能包含PC。

  • 在任何LDM指令中,如果_reglist包含LR,则不能包含PC。

  • 如果指定了写回后缀,_reglist不能包含_Rn_。

当PC出现在LDM指令的_reglist_中时:

  • *加载到PC的值的bit[0]必须为1以确保正确执行,程序会跳转到这个半字对齐的地址。

  • *如果指令是条件执行的,它必须是IT块中的最后一条指令。

条件标志

这些指令不会改变标志位。

示例

 

3.4.7 PUSH 和 POP(压栈/出栈)

 

将寄存器压入(PUSH)或弹出(POP)满递减栈。PUSH和POP分别是STMDB和LDM(或LDMIA)的别名,其内存访问基于SP寄存器,并将最终访问地址写回SP。在此类场景中,推荐使用PUSH和POP助记符。

语法

参数说明:

  • cond:可选条件码(参见第65页“条件执行”)。

  • reglist:非空的寄存器列表(或寄存器范围),用大括号包裹。多个寄存器或范围间需用逗号分隔(示例见第77页)。

操作行为

  • PUSH 按寄存器编号降序将寄存器存入栈,编号最大的寄存器使用最高内存地址,编号最小的寄存器使用最低内存地址。

  • POP 按寄存器编号升序从栈加载寄存器,编号最小的寄存器使用最低内存地址,编号最大的寄存器使用最高内存地址。

  • PUSH 以SP-4为最高内存地址,POP 以SP值为最低内存地址,实现满递减栈。执行完成后:

    • PUSH更新SP指向最后一次存储的最低地址。

    • POP更新SP指向已加载最高地址的上一个位置。

  • 若POP指令的reglist包含PC,则指令完成后会跳转到该地址。此时:

    • 写入PC的值的bit[0]用于更新APSR的T位,且必须为1以确保正确操作。

    • 更多细节参见第76页“LDM与STM”。

限制条件

  • reglist不得包含SP。

  • PUSH指令的reglist不得包含PC。

  • POP指令的reglist若包含LR,则不得同时包含PC。若POP的reglist包含PC:

    • 加载到PC的值的bit[0]必须为1,程序会跳转到此半字对齐地址。

    • 若为条件指令,则必须是IT块的最后一条指令。

条件标志

这些指令不会改变标志位。

示例

PUSH {R0,R4-R7}    ; 将R0、R4、R5、R6、R7压入栈  
PUSH {R2,LR}       ; 将R2和链接寄存器(LR)压入栈  
POP {R0,R6,PC}     ; 从栈弹出R0、R6和PC,并跳转到新PC地址  

3.4.8 LDREX 和 STREX(独占加载/存储)

 

独占式加载与存储寄存器。

语法

参数说明

  • cond:可选条件码(参见第65页“条件执行”)。

  • Rd:用于返回状态的目标寄存器。

  • Rt:待加载或存储的寄存器。

  • Rn:基址寄存器,用于计算内存地址。

  • offset:可选偏移量,作用于 Rn 的值。若省略,则地址直接使用 Rn 的值。

操作行为

  • LDREX、LDREXB 和 LDREXH 分别从内存地址加载一个字(word)、字节(byte)和半字(halfword)。

  • STREX、STREXB 和 STREXH 尝试向内存地址分别存储一个字、字节和半字。

    • 独占存储指令使用的地址必须与最近一次独占加载指令的地址相同。

    • 存储的数据大小必须与之前加载的数据大小一致。

    • 软件必须配对使用独占加载和独占存储指令以实现同步操作(详见第34页“同步原语”)。

  • 若独占存储指令执行成功(完成存储),则向目标寄存器 Rd 写入 0;若失败,则写入 1。

    • 当 Rd 为 0 时,可确保在独占加载和独占存储之间没有其他进程访问该内存位置。

  • 出于性能考虑,应尽量减少独占加载与独占存储指令之间的指令数量。

注意:若独占存储指令的地址与之前的独占加载指令地址不同,执行结果不可预测。

限制条件

使用这些指令时需遵守以下规则:

  • 禁止使用PC寄存器

  • 禁止将SP寄存器用于Rd和Rt

  • STREX指令中,Rd必须与Rt、Rn均不同

  • 偏移量offset的值必须是4的倍数,且范围在0-1020之间

条件标志位

这些指令不会改变处理器标志位。

示例代码

MOV R1, #0x1          ; 初始化'lock taken'值  
try:  
LDREX R0, [LockAddr]  ; 加载锁状态值  
CMP R0, #0            ; 检查锁是否空闲  
ITT EQ                ; 为STREXEQ和CMPEQ设置条件执行块  
STREXEQ R0, R1, [LockAddr] ; 尝试获取锁  
CMPEQ R0, #0          ; 检查是否获取成功  
BNE try               ; 失败则重试  
                      ; 成功获得锁  

3.4.9 CLREX(清除独占状态)

CLREX指令

清除独占状态。

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

操作行为

CLREX指令会使后续的STREX/STREXB/STREXH指令:

  • 向目标寄存器写入1

  • 强制存储操作失败

典型应用场景:
在异常处理程序中,当同步操作(位于独占加载和独占存储指令之间)被异常中断时,通过CLREX强制使存储操作失败。

更多细节请参考第34页"同步原语"。

条件标志位

本指令不会改变处理器标志位。

示例

 
CLREX  

3.5 通用数据处理指令

 

 

 

表28列出了所有数据处理指令的概要信息。

 表28. 数据处理指令总览
助记符 功能简述 详细说明页码
ADC 带进位加法 参见第83页「ADD、ADC、SUB、SBC和RSB」
ADD 加法运算 参见第83页「ADD、ADC、SUB、SBC和RSB」
ADDW 加法运算(宽立即数) 参见第83页「ADD、ADC、SUB、SBC和RSB」
AND 逻辑与 参见第85页「AND、ORR、EOR、BIC和ORN」
ASR 算术右移 参见第86页「ASR、LSL、LSR、ROR和RRX」
BIC 位清除 参见第85页「AND、ORR、EOR、BIC和ORN」
CLZ 前导零计数 参见第87页「CLZ」
CMN 负向比较 参见第88页「CMP和CMN」
CMP 比较运算 参见第88页「CMP和CMN」
EOR 异或运算 参见第85页「AND、ORR、EOR、BIC和ORN」
LSL 逻辑左移 参见第86页「ASR、LSL、LSR、ROR和RRX」
LSR 逻辑右移 参见第86页「ASR、LSL、LSR、ROR和RRX」
MOV 数据搬移 参见第89页「MOV和MVN」
MOVT 高16位数据搬移 参见第91页「MOVT」
MOVW 16位立即数搬移 参见第89页「MOV和MVN」
MVN 数据取反搬移 参见第89页「MOV和MVN」
ORN 逻辑或非 参见第85页「AND、ORR、EOR、BIC和ORN」
ORR 逻辑或 参见第85页「AND、ORR、EOR、BIC和ORN」
RBIT 位序反转 参见第92页「REV、REV16、REVSH和RBIT」
REV 字内字节反序 参见第92页「REV、REV16、REVSH和RBIT」
REV16 半字内字节反序 参见第92页「REV、REV16、REVSH和RBIT」
REVSH 低半字反序并符号扩展 参见第92页「REV、REV16、REVSH和RBIT」
ROR 循环右移 参见第86页「ASR、LSL、LSR、ROR和RRX」
RRX 带扩展循环右移 参见第86页「ASR、LSL、LSR、ROR和RRX」
RSB 反向减法 参见第83页「ADD、ADC、SUB、SBC和RSB」
SADD16 有符号16位加法 参见第93页「SADD16和SADDB」
SADDB 有符号8位加法 参见第93页「SADD16和SADDB」
SASX 有符号加减交换运算 参见第98页「SASX和SSAX」
SSAX 有符号减加交换运算 参见第98页「SASX和SSAX」
SBC 带借位减法 参见第83页「ADD、ADC、SUB、SBC和RSB」
SHADD16 有符号16位半加 参见第94页「SHADD16和SHADDB」
SHADDB 有符号8位半加 参见第94页「SHADD16和SHADDB」

表28. 数据处理指令(续)

助记符功能描述详细说明页码
SHASX 有符号半加半减交换运算 第95页「SHASX与SHSAX」
SHSAX 有符号半减半加交换运算 第95页「SHASX与SHSAX」
SHSUB16 有符号16位半减 第96页「SHSUB16与SHSUB8」
SHSUB8 有符号8位半减 第96页「SHSUB16与SHSUB8」
SSUB16 有符号16位减法 第97页「SSUB16与SSUB8」
SSUB8 有符号8位减法 第97页「SSUB16与SSUB8」
SUB 减法运算 第83页「ADD/ADC/SUB/SBC/RSB」
SUBW 减法运算(宽立即数) 第83页「ADD/ADC/SUB/SBC/RSB」
TEQ 等价测试 第93页「SADD16与SADDB」
TST 位测试 第93页「SADD16与SADDB」
UADD16 无符号16位加法 第100页「UADD16与UADDB」
UADDB 无符号8位加法 第100页「UADD16与UADDB」
UASX 无符号加减交换运算 第101页「UASX与USAX」
USAX 无符号减加交换运算 第101页「UASX与USAX」
UHADD16 无符号16位半加 第102页「UHADD16与UHADDB」
UHADDB 无符号8位半加 第102页「UHADD16与UHADDB」
UHASX 无符号半加半减交换运算 第103页「UHASX与UHSAX」
UHSAX 无符号半减半加交换运算 第103页「UHASX与UHSAX」
UHSUB16 无符号16位半减 第104页「UHSUB16与UHSUB8」
UHSUB8 无符号8位半减 第104页「UHSUB16与UHSUB8」
USAD8 无符号绝对差值和 第106页「USAD8」
USADA8 无符号绝对差值累加 第107页「USADA8」
USUB16 无符号16位减法 第108页「USUB16与USUB8」
USUB8 无符号8位减法 第108页「USUB16与USUB8」

3.5.1 ADD(加法)、ADC(带进位加法)、SUB(减法)、SBC(带借位减法)、RSB(反向减法)

 

加法、带进位加法、减法、带借位减法及反向减法

语法

参数说明:

  • op:指令类型,可选以下之一:

    • ADD:加法

    • ADC:带进位加法

    • SUB:减法

    • SBC:带借位减法

    • RSB:反向减法

  • S:可选后缀。若指定,则根据运算结果更新条件标志位(参见第65页"条件执行")

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器。若省略,则目标寄存器为Rn

  • Rn:存放第一操作数的寄存器

  • Operand2:灵活的第二操作数(选项详见第60页"灵活第二操作数")

  • imm12:0-4095范围内的立即数

操作行为

  • ADD:将Operand2或imm12的值与Rn值相加

  • ADC:将Rn值、Operand2值及进位标志位三者相加

  • SUB:从Rn值中减去Operand2或imm12的值

  • SBC:从Rn值中减去Operand2值,若进位标志为0,结果再减1

  • RSB:用Operand2值减去Rn值(利用Operand2的灵活选项实现特殊运算)

应用场景

  • 使用ADC和SBC实现多字长算术运算(参见第84页"多字长运算示例"及第70页"ADR指令")

  • ADDW等效于使用imm12操作数的ADD语法,SUBW等效于使用imm12操作数的SUB语法

限制条件

使用这些指令时需遵守以下规则:

  • Operand2 不得为SP或PC

  • Rd 仅在ADD和SUB指令中可为SP,且需满足:

    • Rn必须同为SP

    • Operand2的移位操作仅限LSL,且最大移位数3位

  • Rn 仅在ADD和SUB指令中可为SP

  • Rd 仅在特定ADD指令中可为PC:

    ADD{cond} PC, PC, Rm  
    • 不可使用S后缀

    • Rm不得为PC或SP

    • 若为条件指令,必须是IT块的最后一条指令

  • 除上述特殊ADD指令外,Rn 仅在ADD/SUB中可为PC,且需满足:

    • 不可使用S后缀

    • 第二操作数必须为0-4095的立即数

注意:

  1. 使用PC进行加减法时,PC的[1:0]位会强制对齐到b00(字对齐地址)

  2. 生成指令地址时,需根据PC值调整立即数。ARM推荐使用ADR指令替代ADD/SUB(汇编器会自动计算正确立即数)

当指令为 ADD{cond} PC, PC, Rm 且Rd=PC时:

  • 写入PC的值的bit[0]被忽略

  • 强制bit[0]=0后跳转到目标地址

条件标志位

若指定S后缀,指令将根据运算结果更新N/Z/C/V标志位。

示例

ADD R2, R1, R3                  ; R2 = R1 + R3  
SUBS R8, R6, #240                ; R8 = R6 - 240,并更新标志位  
RSB R4, R4, #1280                ; R4 = 1280 - R4  
ADCHI R11, R0, R3                ; 仅当C=1且Z=0时执行:R11 = R0 + R3 + C  

; 64位加法示例:将R2:R3加到R0:R1,结果存至R4:R5  

ADDS R4, R0, R2                  ; 低32位相加(更新标志位)  
ADC R5, R1, R3                   ; 高32位带进位相加  

多寄存器值运算

多字长数值可不使用连续寄存器。示例5:96位减法演示了从R6/R2/R8存储的96位整数中减去R9/R1/R11存储的96位整数,结果存回R6/R9/R2。

示例5:96位减法

SUB  R6, R6, R9    ; 低32位减法  
SBCS R9, R2, R1    ; 中32位带借位减法(更新标志位)  
SBC  R2, R8, R11   ; 高32位带借位减法  

3.5.2 AND(与)、ORR(或)、EOR(异或)、BIC(位清除)、ORN(或非)

逻辑与、或、异或、位清除及或非运算

语法

参数说明:

  • op:指令类型,可选以下之一:

    • AND:逻辑与运算

    • ORR:逻辑或运算(位设置)

    • EOR:逻辑异或运算

    • BIC:逻辑与非运算(位清除)

    • ORN:逻辑或非运算

  • S:可选后缀。若指定,则根据运算结果更新条件标志位(参见第65页"条件执行")

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器(若省略,则目标寄存器为Rn)

  • Rn:存放第一操作数的寄存器

  • Operand2:灵活第二操作数(选项详见第60页"灵活第二操作数")

操作行为

  • AND/EOR/ORR:对Rn和Operand2的值执行按位与/异或/或运算

  • BIC:将Rn的值与Operand2值的反码进行按位与运算

  • ORN:将Rn的值与Operand2值的反码进行按位或运算

限制条件

禁止使用SP(栈指针)或PC(程序计数器)寄存器。

条件标志位

若指定S后缀,这些指令将:

  • 根据运算结果更新N(负标志)和Z(零标志)

  • 在计算Operand2时可能更新C(进位标志),详见第60页"灵活第二操作数"

  • 不影响V(溢出标志)

示例

AND  R9, R2, #0xFF00      ; R9 = R2 & 0xFF00(按位与)
ORREQ R2, R0, R5          ; 当Z=1时执行:R2 = R0 | R5(按位或)
ANDS R9, R8, #0x19        ; R9 = R8 & 0x19,并更新标志位
BIC  R7, R11, #0x18181818 ; R7 = R11 & ~0x18181818(位清除)
ORN  R7, R11, R14, ROR #4 ; R7 = R11 | ~(R14循环右移4位)
ORNS R7, R11, R14, ASR #32; R7 = R11 | (R14算术右移32位),并更新标志位

3.5.3 ASR(算术右移)、LSL(逻辑左移)、LSR(逻辑右移)、ROR(循环右移)、RRX(带扩展循环右移)

 

算术右移、逻辑左移、逻辑右移、循环右移,以及带扩展的循环右移。

语法

其中:

  • op 是以下指令之一:

    • ASR:算术右移

    • LSL:逻辑左移

    • LSR:逻辑右移

    • ROR:循环右移

  • S 为可选后缀。若指定 S,则根据操作结果更新条件码标志位,详见第65页的“条件执行”。

  • Rd 是目标寄存器。

  • Rm 是存放待移位值的寄存器。

  • Rs 是存放移位长度的寄存器,仅使用最低有效字节,范围为0至255。

  • n 是移位长度,范围取决于具体指令:

    • ASR:1至32

    • LSL:0至31

    • LSR:1至32

    • ROR:1至31

注意:
MOVS Rd, Rm 是 LSLS Rd, Rm, #0 的首选语法。

操作

ASR、LSL、LSR 和 ROR 将寄存器 Rm 中的位向左或向右移动指定的位数,移动位数由常量 n 或寄存器 Rs 指定。

RRX 将寄存器 Rm 中的位向右移动 1 位。

在所有这些指令中,结果会被写入 Rd,但 Rm 寄存器中的值保持不变。关于不同指令生成的具体结果,请参阅第62页的“移位操作”。

限制

  • 不要使用 SP(栈指针)或 PC(程序计数器)。

条件标志

如果指定了 S 后缀:

  • 这些指令会根据结果更新 N(负标志)和 Z(零标志)。

  • C(进位标志)会被更新为最后移出的位,除非移位长度为 0(详见第62页的“移位操作”)。

示例

ASR R7, R8, #9     ; 算术右移 9 位  
LSLS R1, R2, #3    ; 逻辑左移 3 位并更新标志位  
LSR R4, R5, #6     ; 逻辑右移 6 位  
ROR R4, R5, R6     ; 按 R6 最低字节的值循环右移  
RRX R4, R5         ; 带扩展的循环右移  

3.5.4 CLZ(前导零计数)

 

前导零计数。

语法

其中:

  • cond 是可选的条件码(详见第65页的“条件执行”)。

  • Rd 是目标寄存器。

  • Rm 是操作数寄存器。

操作

CLZ 指令计算 Rm 中值的前导零数量,并将结果存入 Rd。如果源寄存器中没有置位(即值为 0),则结果为 32;如果最高位(bit[31])已置位,则结果为 0。

限制

  • 不要使用 SP(栈指针)或 PC(程序计数器)。

条件标志

此指令不会改变条件标志。

 示例
 

 

3.5.5 CMP(比较)、CMN(负数比较)

比较与负向比较

语法

其中:

  • cond 为可选条件码(详见第65页"条件执行")。

  • Rn 为存放第一操作数的寄存器。

  • Operand2 为灵活的第二操作数(具体选项详见第60页"灵活第二操作数")。

操作

这些指令将寄存器中的值与Operand2进行比较,并根据结果更新条件标志位,但不会将结果写入寄存器。

  • CMP指令 从Rn值中减去Operand2的值,其功能等同于SUBS指令,但会丢弃运算结果。

  • CMN指令 将Rn值与Operand2相加,其功能等同于ADDS指令,但会丢弃运算结果。

限制

使用这些指令时需注意:

  • 禁止使用PC(程序计数器)

  • Operand2不得为SP(栈指针)

条件标志

这些指令会根据运算结果更新N(负标志)、Z(零标志)、C(进位标志)和V(溢出标志)。

示例

CMP R2, R9            ; 比较R2与R9  
CMN R0, #6400         ; R0值与立即数6400相加比较  
CMPGT SP, R7, LSL #2  ; 若大于条件成立,比较SP与R7左移2位后的值  

3.5.6 MOV(移动)、MVN(取反移动)

数据传送与数据非传送

语法

其中:

  • S 为可选后缀。若指定S,则根据操作结果更新条件码标志位(详见第65页"条件执行")

  • cond 为可选条件码(详见第66页"条件执行")

  • Rd 为目标寄存器

  • Operand2 为灵活的第二操作数(具体选项详见第60页"灵活第二操作数")

  • imm16 为0-65535范围内的任意值

操作

MOV指令 将Operand2的值复制到Rd寄存器:

  • 当MOV指令的Operand2为带有移位操作(非LSL#0)的寄存器时,推荐使用对应的移位指令语法:

    • ASR{S}{cond} Rd, Rm, #n 是 MOV{S}{cond} Rd, Rm, ASR #n 的推荐写法

    • LSL{S}{cond} Rd, Rm, #n 是 MOV{S}{cond} Rd, Rm, LSL #n(当n≠0时)的推荐写法

    • 同理适用于LSR、ROR和RRX操作

  • MOV指令还支持以下移位指令的等价写法:

    • MOV{S}{cond} Rd, Rm, ASR Rs 等价于 ASR{S}{cond} Rd, Rm, Rs

    • 同理适用于LSL、LSR和ROR操作

(详见第86页"ASR、LSL、LSR、ROR和RRX")

MVN指令 对Operand2的值执行按位逻辑非(NOT)操作,并将结果存入Rd。

注意:
MOVW指令功能与MOV相同,但仅支持imm16操作数。

限制条件

仅在MOV指令中可使用SP(栈指针)和PC(程序计数器),但需遵守以下限制:

  • 第二操作数必须为不带移位操作的寄存器

  • 禁止使用S后缀

当MOV指令的目标寄存器为PC时:

  • 写入PC的值的bit[0]将被忽略

  • 程序会跳转到将该值bit[0]强制置0后生成的地址

注意:
虽然可用MOV实现分支跳转,但Arm强烈建议使用BX或BLX指令以保持与Arm指令集的软件兼容性。

条件标志

若指定S后缀,这些指令会:

  • 根据结果更新N(负标志)和Z(零标志)

  • 在计算Operand2时可能更新C(进位标志)(详见第60页"灵活第二操作数")

  • 不影响V(溢出标志)

示例

MOVS R11, #0x000B    ; 将0x000B写入R11,并更新标志位  
MOV R1, #0xFA05      ; 将0xFA05写入R1,不更新标志位  
MOVS R10, R12        ; 将R12值写入R10,并更新标志位  
MOV R3, #23          ; 将立即数23写入R3  
MOV R8, SP           ; 将栈指针值写入R8  
MVNS R2, #0xF        ; 将0xF按位取反(0xFFFFFFF0)写入R2,并更新标志位  

3.5.7 MOVT(移动高16位)

高半字数据传送

语法

其中:

  • cond 为可选条件码(详见第65页"条件执行")

  • Rd 为目标寄存器

  • imm16 为16位立即数

操作

MOVT将16位立即数imm16写入目标寄存器的高半字(Rd[31:16]),该操作不会影响寄存器的低半字(Rd[15:0])。

MOV与MOVT指令配合使用,可生成任意32位常数。

限制

  • 目标寄存器Rd不能为SP(栈指针)或PC(程序计数器)

条件标志

本指令不会改变任何条件标志位。

示例

MOVT R3, #0xF123  ; 将0xF123写入R3的高半字  
                  ; R3的低半字和APSR状态寄存器保持不变  
 

3.5.8 REV(字节反转)、REV16(半字反转)、REVSH(有符号半字反转)、RBIT(位反转)

 

字节序反转与位序反转

语法

其中:

  • op 为以下指令之一:

    • REV:反转字(32位)内的字节顺序

    • REV16:分别反转每个半字(16位)内的字节顺序

    • REVSH:反转低半字的字节顺序并符号扩展至32位

    • RBIT:反转32位字中的位顺序

  • cond 为可选条件码(详见第65页"条件执行")

  • Rd 为目标寄存器

  • Rn 为存放操作数的寄存器

操作

这些指令用于改变数据的字节序:

  • REV:实现32位数据的字节序转换

    • 大端序 ↔ 小端序

  • REV16:实现16位半字的字节序转换

    • 大端序 ↔ 小端序(每个半字独立处理)

  • REVSH:实现16位有符号数据的转换

    • 大端序有符号数据 → 32位小端序有符号数据

    • 小端序有符号数据 → 32位大端序有符号数据

限制

  • 禁止使用SP(栈指针)或PC(程序计数器)

条件标志

这些指令不会改变任何条件标志位。

示例

REV R3, R7     ; 反转R7值的字节顺序后写入R3  
REV16 R0, R0   ; 反转R0中每个半字的字节顺序  
REVSH R0, R5   ; 反转有符号半字并符号扩展  
REVHS R3, R7   ; 满足HS(无符号大于等于)条件时执行字节反转  
RBIT R7, R8    ; 反转R8值的位顺序后写入R7  

3.5.9 SADD16和SADD8(有符号16位/8位加法)

有符号16位加法与有符号8位加法

语法

其中:

  • op 为以下指令之一:

    • SADD16:执行两组16位有符号整数加法

    • SADDB:执行四组8位有符号整数加法

  • cond 为可选条件码(详见第65页"条件执行")

  • Rd 为目标寄存器

  • Rn 为第一操作数寄存器

  • Rm 为第二操作数寄存器

操作

这些指令实现并行半字/字节加法运算:

SADD16指令:

  1. 将第一操作数的每个半字与第二操作数对应半字相加

  2. 结果写入目标寄存器的对应半字

SADDB指令:

  1. 将第一操作数的每个字节与第二操作数对应字节相加

  2. 结果写入目标寄存器的对应字节

限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

条件标志

这些指令不会改变任何条件标志位。

示例

SADD16 R1, R0     ; 将R0的每个半字与R1对应半字相加,结果写入R1对应半字  
SADDB R4, R0, R5  ; 将R0的每个字节与R5对应字节相加,结果写入R4对应字节  

3.5.10 SHADD16和SHADD8(有符号半字/字节加法并右移)

 

有符号半减加法(16位/8位)

语法

参数说明:

  • op 支持以下指令:

    • SHADD16:16位有符号半减加法

    • SHADDB:8位有符号半减加法

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:第一操作数寄存器

  • Rm:第二操作数寄存器

功能描述

实现16位/8位数据相加后右移一位(结果减半)的并行运算:

SHADD16指令:

  1. 对两个操作数的对应16位半字执行加法

  2. 将结果算术右移1位(相当于除以2)

  3. 将处理后的半字结果写入目标寄存器

SHADDB指令:

  1. 对两个操作数的对应8位字节执行加法

  2. 将结果算术右移1位(相当于除以2)

  3. 将处理后的字节结果写入目标寄存器

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

本指令不影响任何状态标志

应用示例

SHADD16 R1, R0     ; R0和R1的半字相加后减半,结果存入R1对应半字
SHADDB R4, R0, R5  ; R0和R5的字节相加后减半,结果存入R4对应字节

3.5.11 SHASX和SHSAX(有符号半字交叉加减并右移)

 

有符号半减加交换/有符号半减减加交换

语法

参数说明:

  • op 支持以下指令:

    • SHASX:半减加交换(先加后减)

    • SHSAX:半减减加交换(先减后加)

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn/Rm:第一/第二操作数寄存器

功能描述

SHASX指令:

  1. 将Rn高半字与Rm低半字相加

  2. 结果右移1位(半减)后写入Rd高半字

  3. 将Rn低半字与Rm高半字相减

  4. 结果右移1位(半减)后写入Rd低半字

SHSAX指令:

  1. 将Rn高半字与Rm低半字相减

  2. 结果右移1位(半减)后写入Rd低半字

  3. 将Rn低半字与Rm高半字相加

  4. 结果右移1位(半减)后写入Rd高半字

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

不影响任何状态标志

应用示例

SHASX R7, R4, R2  ; (R4[31:16]+R2[15:0])>>1 → R7[31:16]  
                  ; (R4[15:0]-R2[31:16])>>1 → R7[15:0]  

3.5.12 SHSUB16和SHSUB8(有符号半字/字节减法并右移)

有符号半减减法(16位/8位)

语法

参数说明:

  • op 支持以下指令:

    • SHSUB16:16位有符号半减减法

    • SHSUB8:8位有符号半减减法

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:被减数寄存器

  • Rm:减数寄存器

功能描述

实现16位/8位数据相减后右移一位(结果减半)的并行运算:

SHSUB16指令:

  1. 对两个操作数的对应16位半字执行减法(Rn-Rm)

  2. 将结果算术右移1位(结果减半)

  3. 处理后的半字结果写入目标寄存器

SHSUB8指令:

  1. 对两个操作数的对应8位字节执行减法(Rn-Rm)

  2. 将结果算术右移1位(结果减半)

  3. 处理后的字节结果写入目标寄存器

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

不影响任何状态标志

应用示例

SHSUB16 R1, R0     ; 用R0的各个半字减去R1对应半字  
                   ; 结果减半后写回R1对应半字  

SHSUB8 R4, R0, R5  ; 用R0的各个字节减去R5对应字节  
                   ; 结果减半后写入R4对应字节  

3.5.13 SSUB16和SSUB8(有符号16位/8位减法)

 

有符号减法(16位/8位)

语法

参数说明:

  • op 为以下指令之一:

    • SSUB16:执行两组16位有符号整数减法

    • SSUB8:执行四组8位有符号整数减法

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:被减数寄存器

  • Rm:减数寄存器

功能描述

SSUB16指令:

  1. 将Rn的每个半字减去Rm对应的半字

  2. 将差值结果写入目标寄存器的对应半字

SSUB8指令:

  1. 将Rn的每个字节减去Rm对应的字节

  2. 将差值结果写入目标寄存器的对应字节

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

这些指令不会改变任何状态标志

应用示例

SSUB16 R1, R0     ; 用R1的各个半字减去R0对应半字,结果存入R1对应半字  
SSUB8 R4, R0, R5  ; 用R0的各个字节减去R5对应字节,结果存入R4对应字节  

3.5.14 SASX和SSAX(有符号半字交叉加减)

 

有符号加交换减/有符号减交换加

语法

 

参数说明:

  • op 支持以下指令:

    • SASX:有符号加交换减(高半字加,低半字减)

    • SSAX:有符号减交换加(高半字减,低半字加)

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn/Rm:第一/第二操作数寄存器

功能描述

SASX指令:

  1. 将Rn高半字与Rm低半字执行有符号加法

  2. 结果写入Rd高半字

  3. 将Rn低半字与Rm高半字执行有符号减法

  4. 结果写入Rd低半字

SSAX指令:

  1. 将Rn高半字与Rm低半字执行有符号减法

  2. 结果写入Rd低半字

  3. 将Rn低半字与Rm高半字执行有符号加法

  4. 结果写入Rd高半字

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

不影响任何状态标志

应用示例

 

SASX R0, R4, R5   ; 将R4高半位[31:16]与R5低半位[15:0]相加 → R0[31:16]  
                  ; 将R4低半位[15:0]减去R5高半位[31:16] → R0[15:0]  

SSAX R7, R3, R2   ; 将R3低半位[15:0]减去R2高半位[31:16] → R7[15:0]  
                  ; 将R3高半位[31:16]与R2低半位[15:0]相加 → R7[31:16]  

3.5.15 TST(测试)、TEQ(测试相等)

 

位测试与等价测试

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

  • Rn:存放第一操作数的寄存器

  • Operand2:灵活的第二操作数(选项详见第60页"灵活第二操作数")

功能描述

这些指令测试寄存器值与Operand2的关系,并根据结果更新条件标志位(不保留运算结果):

TST指令:

  • 执行Rn与Operand2的按位与操作(功能同ANDS指令,但丢弃结果)

  • 测试Rn特定位:设置Operand2对应位为1,其余位为0

TEQ指令:

  • 执行Rn与Operand2的按位异或操作(功能同EORS指令,但丢弃结果)

  • 测试两值相等性(不影响V/C标志)

  • 符号位测试:运算后N标志反映两操作数符号位的异或结果

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

  • 根据结果更新N(负标志)和Z(零标志)

  • 计算Operand2时可能更新C(进位标志)

  • 不影响V(溢出标志)

应用示例

 

TST R0, #0x3F8      ; 测试R0与0x3F8的按位与,更新APSR但丢弃结果  
TEQEQ R10, R9       ; 条件执行:测试R10与R9是否相等,更新APSR但丢弃结果  

3.5.16 UADD16和UADD8(无符号16位/8位加法)

无符号加法(16位/8位)

语法

参数说明:

  • op 为以下指令之一:

    • UADD16:执行两组16位无符号整数加法

    • UADDB:执行四组8位无符号整数加法

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:第一操作数寄存器

  • Rm:第二操作数寄存器

功能描述

UADD16指令:

  1. 将Rn的每个16位半字与Rm对应半字相加

  2. 无符号结果写入目标寄存器对应半字

UADDB指令:

  1. 将Rn的每个8位字节与Rm对应字节相加

  2. 无符号结果写入目标寄存器对应字节

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

这些指令不会改变任何状态标志

应用示例

 

UADD16 R1, R0     ; 将R0各半字与R1对应半字相加,结果存入R1  
UADDB R4, R0, R5  ; 将R0各字节与R5对应字节相加,结果存入R4  

3.5.17 UASX和USAX(无符号半字交叉加减)

无符号加交换减/无符号减交换加

语法

参数说明:

  • op 为以下指令之一:

    • UASX:无符号加交换减(高半字加,低半字减)

    • USAX:无符号减交换加(高半字减,低半字加)

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn/Rm:第一/第二操作数寄存器

功能描述

UASX指令:

  1. 将Rn高半位[31:16]与Rm低半位[15:0]相加 → Rd[31:16]

  2. 将Rn低半位[15:0]减去Rm高半位[31:16] → Rd[15:0]

USAX指令:

  1. 将Rn高半位[31:16]减去Rm低半位[15:0] → Rd[15:0]

  2. 将Rn低半位[15:0]与Rm高半位[31:16]相加 → Rd[31:16]

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

不影响任何状态标志

应用示例

UASX R0, R4, R5   ; 将R4高半字[31:16]与R5低半字[15:0]相加 → R0[31:16]  
                  ; 将R4低半字[15:0]减去R5高半字[31:16] → R0[15:0]  

USAX R7, R3, R2   ; 将R3高半字[31:16]减去R2低半字[15:0] → R7[15:0]  
                  ; 将R3低半字[15:0]与R2高半字[31:16]相加 → R7[31:16]  

3.5.18 UHADD16和UHADD8(无符号半字/字节加法并右移)

无符号半减加法(16位/8位)

语法

 

参数说明:

  • op 为以下指令之一:

    • UHADD16:16位无符号半减加法

    • UHADDB:8位无符号半减加法

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:第一操作数寄存器

  • Rm:第二操作数寄存器

功能描述

UHADD16指令:

  1. 将Rn与Rm的对应16位半字相加

  2. 结果右移1位(数值减半)

  3. 无符号结果写入目标寄存器对应半字

UHADDB指令:

  1. 将Rn与Rm的对应8位字节相加

  2. 结果右移1位(数值减半)

  3. 无符号结果写入目标寄存器对应字节

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

这些指令不会改变任何状态标志

应用示例

UHADD16 R7, R3    ; R7与R3的半字相加后减半,结果存入R7对应半字  
UHADDB R4, R0, R5 ; R0与R5的字节相加后减半,结果存入R4对应字节  

3.5.19 UHASX和UHSAX(无符号半字交叉加减并右移)

 

无符号半减加交换减/无符号半减减交换加

语法

参数说明:

  • op 为以下指令之一:

    • UHASX:无符号半减加交换减(高半字加,低半字减)

    • UHSAX:无符号半减减交换加(高半字减,低半字加)

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn/Rm:第一/第二操作数寄存器

功能描述

UHASX指令:

  1. 将Rn高半字[31:16]与Rm低半字[15:0]相加 → 结果右移1位 → Rd[31:16]

  2. 将Rn低半字[15:0]减去Rm高半字[31:16] → 结果右移1位 → Rd[15:0]

UHSAX指令:

  1. 将Rn高半字[31:16]减去Rm低半字[15:0] → 结果右移1位 → Rd[31:16]

  2. 将Rn低半字[15:0]与Rm高半字[31:16]相加 → 结果右移1位 → Rd[15:0]

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

不影响任何状态标志

应用示例

UHASX R7, R4, R2  ; (R4[31:16] + R2[15:0])>>1 → R7[31:16]  
                  ; (R4[15:0] - R2[31:16])>>1 → R7[15:0]  

 

UHSAX R0, R3, R5  ; 将R3高半字[31:16]减去R5低半字[15:0] → 结果右移1位 → R0[31:16]  
                  ; 将R3低半字[15:0]与R5高半字[31:16]相加 → 结果右移1位 → R0[15:0]  
 

3.5.20 UHSUB16和UHSUB8(无符号半字/字节减法并右移)

 

无符号半减减法(16位/8位)

语法

参数说明:

  • op 为以下指令之一:

    • UHSUB16:执行两组16位无符号整数减法,结果减半后写入目标寄存器

    • UHSUB8:执行四组8位无符号整数减法,结果减半后写入目标寄存器

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:被减数寄存器

  • Rm:减数寄存器

功能描述

UHSUB16指令:

  1. 将Rn的每个16位半字减去Rm对应半字

  2. 结果算术右移1位(数值减半)

  3. 无符号结果写入目标寄存器对应半字

UHSUB8指令:

  1. 将Rn的每个8位字节减去Rm对应字节

  2. 结果算术右移1位(数值减半)

  3. 无符号结果写入目标寄存器对应字节

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

这些指令不会改变任何状态标志

应用示例

UHSUB16 R1, R0    ; R0各半字减去R1对应半字,结果减半后写回R1  
UHSUB8 R4, R2, R3 ; R2各字节减去R3对应字节,结果减半后写入R4  

UHSUB8 R4, R0, R5  ; 将R0各字节减去R5对应字节,结果减半后写入R4对应字节  

3.5.21 SEL(选择)

 

字节选择指令

语法

 

参数说明:

  • cond:可选条件码(标准汇编语法字段)

  • Rd:目标寄存器

  • Rn:第一操作数寄存器

  • Rm:第二操作数寄存器

功能描述

SEL指令根据APSR.GE标志位的值,从两个操作数中选择字节:

  1. 读取APSR.GE各位的值

  2. 根据GE标志位的状态,选择Rn或Rm中的对应字节写入目标寄存器

使用限制

无特殊限制

标志位影响

本指令不会改变任何状态标志

应用示例

 

SADD16 R0, R1, R2  ; 执行加法并设置GE标志位  
SEL R0, R0, R3     ; 根据GE标志选择R0或R3中的字节写入R0  

3.5.22 USAD8(无符号绝对差和)

 

无符号绝对差值和

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:第一操作数寄存器

  • Rm:第二操作数寄存器

功能描述

USAD8指令执行以下操作:

  1. 计算Rn与Rm对应字节的无符号差值(Rn-Rm)

  2. 对所有字节差值的绝对值求和

  3. 将累加结果写入目标寄存器

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

本指令不会改变任何状态标志

应用示例

USAD8 R1, R4, R0  ; 计算R4与R0各字节绝对差值和,结果存入R1  
USAD8 R0, R5      ; 计算R0与R5各字节绝对差值和,结果存回R0  

3.5.23 USADA8(无符号绝对差和累加)

 

无符号绝对差值和累加

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:第一操作数寄存器

  • Rm:第二操作数寄存器

  • Ra:累加值寄存器

功能描述

USADA8指令执行以下操作:

  1. 计算Rn与Rm对应字节的无符号差值(Rn-Rm)

  2. 对所有字节差值的绝对值求和

  3. 将累加值Ra与绝对差值和相加

  4. 最终结果写入目标寄存器

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

本指令不会改变任何状态标志

应用示例

 

USADA8 R1, R0, R6     ; 计算R0与R6字节绝对差值和,加上R1原值,结果存R1  
USADA8 R4, R0, R5, R2 ; 计算R0与R5字节绝对差值和,加上R2值,结果存R4  

3.5.24 USUB16和USUB8(无符号16位/8位减法)

 

无符号减法(16位/8位)

语法

参数说明:

  • op 为以下指令之一:

    • USUB16:16位无符号减法

    • USUB8:8位无符号减法

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:被减数寄存器

  • Rm:减数寄存器

功能描述

USUB16指令:

  1. 将Rn的每个16位半字减去Rm对应半字

  2. 无符号结果写入目标寄存器对应半字

USUB8指令:

  1. 将Rn的每个8位字节减去Rm对应字节

  2. 无符号结果写入目标寄存器对应字节

使用限制

  • 禁止使用SP(栈指针)和PC(程序计数器)

标志位影响

这些指令不会改变任何状态标志

应用示例

 

USUB16 R1, R0     ; R0各半字减去R1对应半字,结果存入R1  
USUB8 R4, R0, R5  ; R0各字节减去R5对应字节,结果存入R4  

3.6 乘法与除法指令

 

 

表29. 乘除指令汇总表
助记符 简要说明 详见章节
MLA 乘加(32位结果) 第110页 MUL、MLA和MLS
MLS 乘减(32位结果) 第110页 MUL、MLA和MLS
MUL 乘法(32位结果) 第110页 MUL、MLA和MLS
SDIV 有符号除法 第124页 SDIV和UDIV
SMLA[B,T] 有符号半字乘加 第112页 SMLA和SMLAW
SMLAD, SMLADX 有符号双乘加 第114页 SMLAD
SMLAL 有符号长乘加(32x32+64,64位结果) 第115页 SMLAL和SMLALD
SMLAL[B,T] 有符号半字长乘加 第115页 SMLAL和SMLALD
SMLALD, SMLALDX 有符号双长乘加 第115页 SMLAL和SMLALD
SMLAW[B,T] 有符号字乘半字加 第112页 SMLA和SMLAW
SMLSD 有符号双乘减 第117页 SMLSD和SMLSLD
SMLSLD 有符号双长乘减 第117页 SMLSD和SMLSLD
SMMLA 有符号高位乘加 第119页 SMMLA和SMMLS
SMMLS, SMMLSR 有符号高位乘减 第119页 SMMLA和SMMLS
SMUAD, SMUADX 有符号双乘加 第121页 SMUAD和SMUSD
SMUL[B,T] 有符号字乘半字 第122页 SMUL和SMULW
SMMUL, SMMULR 有符号高位乘法 第120页 SMMUL
SMULL 有符号长乘法(32x32,64位结果) 第120页 SMMUL
SMULWB, SMULWT 有符号字乘半字 第122页 SMUL和SMULW
SMUSD, SMUSDX 有符号双乘减 第121页 SMUAD和SMUSD
UDIV 无符号除法 第112页 SMLA和SMLAW
UMAAL 无符号长乘加加(32x32+32+32,64位结果) 第111页 UMULL、UMAAL和UMLAL
UMLAL 无符号长乘加(32x32+64,64位结果) 第111页 UMULL、UMAAL和UMLAL
UMULL 无符号长乘法(32x32,64位结果) 第111页 UMULL、UMAAL和UMLAL

 

3.6.1 MUL(乘法)、MLA(乘累加)、MLS(乘减)

 

32位乘法、乘加与乘减(32位操作数,32位结果)

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

  • S:可选后缀。若指定则根据结果更新条件标志位

  • Rd:目标寄存器(若省略则默认为Rn)

  • Rn/Rm:乘数寄存器

  • Ra:累加/减数寄存器

功能描述

MUL指令:

  • 计算Rn × Rm,结果的低32位存入Rd

MLA指令:

  • 计算 (Rn × Rm) + Ra,结果的低32位存入Rd

MLS指令:

  • 计算 Ra - (Rn × Rm),结果的低32位存入Rd

注:运算结果与操作数的有符号性无关

使用限制

  • 禁止使用SP和PC

  • 若MUL指令带S后缀:

    • 所有寄存器必须为R0-R7

    • Rd必须与Rm相同

    • 不可使用条件后缀

标志位影响

若指定S后缀,MUL指令会:

  • 根据结果更新N(负)和Z(零)标志

  • 不影响C(进位)和V(溢出)标志

应用示例

 

MUL R10, R2, R5     ; R10 = R2 × R5  
MLA R10, R2, R1, R5 ; R10 = (R2 × R1) + R5  
MULS R0, R2, R2     ; R0 = R2² 并更新标志位  
MULLT R2, R3, R2    ; 条件执行:R2 = R3 × R2  
MLS R4, R5, R6, R7  ; R4 = R7 - (R5 × R6)  

3.6.2 UMULL(无符号长乘法)、UMAAL(无符号双累加长乘法)、UMLAL(无符号长乘累加)

 

无符号长乘法(可选累加),32位操作数生成64位结果

语法

参数说明:

  • op 为以下指令之一:

    • UMULL:无符号长乘法

    • UMAAL:无符号双累加长乘法

    • UMLAL:无符号累加长乘法

  • cond:可选条件码(参见第65页"条件执行")

  • RdHi/RdLo:目标寄存器(同时存储累加值)

  • Rn/Rm:第一/第二操作数寄存器

功能描述

UMULL指令:

  1. 对两个无符号32位整数执行乘法

  2. 结果的低32位存入RdLo

  3. 结果的高32位存入RdHi

UMAAL指令:

  1. 执行两个无符号32位整数乘法

  2. 将RdHi值加到64位乘积结果

  3. 再将RdLo值加到当前结果

  4. 最终结果的高32位存入RdHi

  5. 最终结果的低32位存入RdLo

UMLAL指令:

  1. 执行两个无符号整数乘法

  2. 将64位乘积与RdHi:RdLo的64位值相加

  3. 结果写回RdHi和RdLo

使用限制

  • 禁止使用SP和PC

  • RdHi与RdLo必须为不同寄存器

标志位影响

这些指令不影响任何状态标志

应用示例

 

UMULL R0, R4, R5, R6  ; 计算R5×R6,高32位存入R4,低32位存入R0  

UMAAL R3, R6, R2, R7  ; 计算R2×R7 + R6 + R3,高32位存入R6,低32位存入R3  

UMAAL R2, R1, R3, R5  ; 计算R3×R5 + R1:R2,结果存入R1(高32位)和R2(低32位)  

 

3.6.3 SMLA(有符号乘累加)、SMLAW(有符号乘累加半字)

有符号半字乘加,有符号半字乘加指令

语法

 

参数说明:

  • op 为以下指令类型:

    • SMLA:有符号半字长乘加

      • X/Y指定源寄存器半字选择:

        • B:使用低半字[15:0]

        • T:使用高半字[31:16]

    • SMLAW:有符号字乘半字加

      • Y指定Rm寄存器半字选择(T/B同上)

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器(可省略,默认为Rn)

  • Rn/Rm:乘数寄存器

  • Ra:累加数寄存器

功能描述

SMLA系列指令(SMLABB/SMLABT/SMLATB/SMLATT):

  1. 按指定选择Rn和Rm的半字进行有符号乘法

  2. 将32位乘积与Ra值相加

  3. 结果写入Rd

  4. 忽略源寄存器未指定的半字

SMLAW系列指令(SMLAWB/SMLAWT):

  1. 将Rn的32位有符号值与Rm指定半字相乘

  2. 取48位乘积的高32位与Ra相加

  3. 结果写入Rd(忽略乘积低16位)

  4. 若累加发生溢出,则设置APSR的Q标志(乘法不会溢出)

使用限制

  • 禁止使用SP和PC

标志位影响

  • 若检测到溢出,则设置APSR的Q标志位

应用示例

SMLABB R5, R6, R4, R1  ; R6[15:0] × R4[15:0] + R1 → R5  
SMLATB R5, R6, R4, R1  ; R6[31:16] × R4[15:0] + R1 → R5  
SMLATT R5, R6, R4, R1  ; R6[31:16] × R4[31:16] + R1 → R5  
SMLABT R5, R6, R4, R1  ; R6[15:0] × R4[31:16] + R1 → R5  
SMLABT R4, R3, R2      ; R4[15:0] × R3[31:16] + R2 → R4  

SMLAWB R10, R2, R5, R3 ; R2 × R5[15:0] + R3(取高32位)→ R10  
SMLAWT R10, R2, R1, R5 ; R2 × R1[31:16] + R5(取高32位)→ R10  

3.6.4 SMLAD(有符号双乘累加)

 

有符号双半字乘加指令

语法

 

参数说明:

  • op 为以下指令类型:

    • SMLAD:有符号双半字乘加

    • SMLADX:有符号双半字反向乘加

      • X指定半字交叉相乘模式(存在时采用高低半字交叉相乘)

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:第一操作数寄存器

  • Rm:第二操作数寄存器

  • Ra:累加值寄存器

功能描述

将操作数视为四个16位有符号半字:

标准模式(无X后缀):

  1. Rn[31:16] × Rm[31:16] + Rn[15:0] × Rm[15:0]

  2. 乘积和与Ra相加

  3. 32位结果写入Rd

交叉模式(X后缀):

  1. Rn[31:16] × Rm[15:0] + Rn[15:0] × Rm[31:16]

  2. 乘积和与Ra相加

  3. 32位结果写入Rd

使用限制

  • 禁止使用SP和PC

标志位影响

不影响任何状态标志

应用示例

SMLAD R10, R2, R1, R5    ; R2[31:16]×R1[31:16] + R2[15:0]×R1[15:0] + R5 → R10  
SMLADX R0, R2, R4, R6    ; R2[31:16]×R4[15:0] + R2[15:0]×R4[31:16] + R6 → R0  

3.6.5 SMLAL(有符号长乘累加)、SMLALD(有符号双长乘累加)

 

有符号长乘加指令(支持半字/双半字操作)

语法

 

参数说明:

  • op 为以下指令类型:

    • SMLAL:有符号长乘加(32位×32位→64位)

    • SMLALXY:有符号半字长乘加(X/Y指定半字选择)

      • B:使用低半字[15:0]

      • T:使用高半字[31:16]

    • SMLALD:有符号双半字长乘加

    • SMLALDX:有符号双半字反向长乘加(X存在时交叉相乘)

  • cond:可选条件码(参见第65页)

  • RdHi/RdLo:目标寄存器(存储64位结果/累加值)

  • Rn/Rm:操作数寄存器

功能描述

SMLAL指令:

  1. 对Rn和Rm的有符号32位值执行乘法

  2. 将64位乘积与RdHi:RdLo的64位值相加

  3. 结果写回RdHi和RdLo

SMLALXY指令(如SMLALBB/SMLALBT等):

  1. 按X/Y选择Rn和Rm的半字进行有符号乘法

  2. 将符号扩展的32位乘积与64位累加值相加

  3. 结果写回RdHi:RdLo(忽略未选半字)

SMLALD/SMLALDX指令:

  1. 标准模式(无X):Rn[31:16]×Rm[31:16] + Rn[15:0]×Rm[15:0]

  2. 交叉模式(X后缀):Rn[31:16]×Rm[15:0] + Rn[15:0]×Rm[31:16]

  3. 乘积和与64位累加值相加后写回目标寄存器

源寄存器中未指定的半字数据将被忽略

SMLALD和SMLALDX指令将RnRn和RmRm中的值解释为四个半字的16位有符号补码整数。这些指令的功能如下:

  • 如果未包含X,则将RnRn的高半字有符号值与RmRm的高半字有符号值相乘,同时将RnRn的低半字有符号值与RmRm的低半字有符号值相乘。

  • 如果包含X,则将RnRn的高半字有符号值与RmRm的低半字有符号值相乘,同时将RnRn的低半字有符号值与RmRm的高半字有符号值相乘。

  • 将两个乘法结果与RdLoRdLo和RdHtRdHt中的64位有符号值相加,生成最终的64位乘积。

  • 将64位乘积写入RdLoRdLo和RdHtRdHt中。

限制条件

在这些指令中:

  • 不能使用SP或PC寄存器。

  • RdHtRdHt和RdLoRdLo必须是不同的寄存器。

条件标志位

这些指令不会影响条件码标志位。

示例

 

 

| SMLAL | R4, R5, R3, R8 | ; 将R3和R8的值相乘,结果与R5:R4相加后写入R5:R4 |
|---|---|
| SMLALBT | R2, R1, R6, R7 | ; 将R6的低半字与R7的高半字相乘,符号扩展为32位后与R1:R2相加,结果写入R1:R2 |
| SMLALTB | R2, R1, R6, R7 | ; 将R6的高半字与R7的低半字相乘,符号扩展为32位后与R1:R2相加,结果写入R1:R2 |
| SMLALD | R6, R8, R5, R1 | ; 将R5和R1的高半字相乘,低半字相乘,结果与R8:R6相加后写入R8:R6 |
| SMLALDX | R6, R8, R5, R1 | ; 将R5的高半字与R1的低半字相乘,R5的低半字与R1的高半字相乘,结果与R8:R6相加后写入R8:R6 |

3.6.6 SMLSD(有符号双乘减)、SMLSLD(有符号双长乘减)

 

SMLSD 和 SMLSLD

有符号乘减双半字与有符号长乘减双半字

语法

 

其中:

  • op 是以下指令之一:

    • SMLSD:有符号乘减双半字。

    • SMLSDX:有符号乘减双半字(半字交换)。

    • SMLSLD:有符号长乘减双半字。

    • SMLSLDX:有符号长乘减双半字(半字交换)。

    • 如果包含 X,则乘法操作为“低半字 × 高半字”和“高半字 × 低半字”。

    • 如果省略 X,则乘法操作为“低半字 × 低半字”和“高半字 × 高半字”。

  • cond 是可选的条件码(参见第65页的“条件执行”)。

  • Rd 是目标寄存器。

  • RnRm 是存放第一和第二操作数的寄存器。

  • Ra 是存放累加值的寄存器。

操作

SMLSD 指令 将第一和第二操作数的值解释为四个有符号半字。该指令执行以下操作:

  1. 可选地交换第二操作数的半字顺序。

  2. 执行两次有符号 16 × 16 位半字乘法。

  3. 将高半字乘法的结果从低半字乘法的结果中减去。

  4. 将减法结果与有符号累加值相加。

  5. 将加法结果写入目标寄存器。

SMLSLD 指令 将 Rn 和 Rm 的值解释为四个有符号半字。该指令执行以下操作:

  1. 可选地交换第二操作数的半字顺序。

  2. 执行两次有符号 16 × 16 位半字乘法。

  3. 将高半字乘法的结果从低半字乘法的结果中减去。

  4. 将减法结果与 RdHi 和 RdLo 中的64位值相加。

  5. 将64位加法结果写入 RdHi 和 RdLo

限制条件

在这些指令中:

  • 不能使用 SP 或 PC 寄存器。

条件标志位

  • 如果累加操作溢出,该指令会设置 Q 标志位。

  • 在乘法或减法操作期间不会发生溢出。

对于Thumb指令集,这些指令不会影响条件码标志位。

示例

 

SMLSD R0, R4, R5, R6
; 将R4的低半字与R5的低半字相乘,R4的高半字与R5的高半字相乘,
; 用第一个乘积减去第二个乘积,再加上R6的值,最终结果写入R0

SMLSDX R1, R3, R2, R0
; 将R3的低半字与R2的高半字相乘,R3的高半字与R2的低半字相乘,
; 用第一个乘积减去第二个乘积,再加上R0的值,最终结果写入R1

SMLSLD R3, R6, R2, R7
; 将R6的低半字与R2的低半字相乘,R6的高半字与R2的高半字相乘,
; 用第一个乘积减去第二个乘积,再加上R6:R3的值,最终结果写入R6:R3

SMLSLDX R3, R6, R2, R7
; 将R6的低半字与R2的高半字相乘,R6的高半字与R2的低半字相乘,
; 用第一个乘积减去第二个乘积,再加上R6:R3的值,最终结果写入R6:R3

3.6.7 SMMLA(有符号矩阵乘累加)、SMMLS(有符号矩阵乘减)

 

SMMLA 和 SMMLS

有符号高字乘加与有符号高字乘减

语法

其中:

  • op 为以下指令之一:

    • SMMLA:有符号高字乘加

    • SMMLS:有符号高字乘减

  • R 为舍入标志。若指定 R,则结果将进行舍入而非截断,即在提取高字前先给乘积加上 0x80000000

  • cond 为可选条件码(参见第65页"条件执行")

  • Rd 为目标寄存器

  • RnRm 为存放乘法操作数的寄存器

  • Ra 为存放累加值的寄存器

操作

SMMLA指令 将 Rn 和 Rm 的值解释为有符号32位字:

  1. 对 Rn 和 Rm 的值进行乘法运算

  2. 可选地通过加 0x80000000 对结果进行舍入

  3. 提取结果的最高有效32位

  4. 将 Ra 的值与提取的有符号值相加

  5. 将加法结果写入 Rd

SMMLS指令 将 Rn 和 Rm 的值解释为有符号32位字:

  1. 对 Rn 和 Rm 的值进行乘法运算

  2. 可选地通过加 0x80000000 对结果进行舍入

  3. 提取结果的最高有效32位

  4. 从 Ra 的值中减去提取的结果值

  5. 将减法结果写入 Rd

限制条件

这些指令中:

  • 不能使用 SP 或 PC 寄存器

条件标志位

这些指令不影响条件码标志位

示例

 

SMMLA R0, R4, R5, R6 ; 将 R4 和 R5 相乘,提取高32位,
; 加上 R6,截断后写入 R0
SMMLAR R6, R2, R1, R4 ; 将 R2 和 R1 相乘,提取高32位,
; 加上 R4,舍入后写入 R6
SMMLSR R3, R6, R2, R7 ; 将 R6 和 R2 相乘,提取高32位,
; 减去 R7,舍入后写入 R3

3.6.8 SMMUL(有符号矩阵乘法)

 

SMMUL
有符号高字乘法

语法

其中:
• op 为以下指令之一:

  • SMMUL:有符号高字乘法

  • R:舍入标志。若指定R,则结果将进行舍入而非截断。此时会在提取高字前给乘积加上常量0x80000000
    • cond 为可选条件码(参见第65页"条件执行")
    • Rd 为目标寄存器
    • RnRm 为存放操作数的寄存器

操作

SMMUL指令将Rn和Rm的值解释为32位有符号补码整数。该指令执行以下操作:

  1. 对Rn和Rm的值进行乘法运算

  2. 可选地对结果进行舍入,否则执行截断

  3. 将结果的最高有效32位有符号值写入Rd

限制条件

本指令中:

  • 不得使用SP或PC寄存器

条件标志位

本指令不影响条件码标志位

示例

 

SMMUL R0, R4, R5 ; 将R4和R5相乘,截取高32位
; 并写入R0
SMMULR R6, R2, R1 ; 将R6和R2相乘,对高32位舍入
; 并写入R6

3.6.9 SMUAD(有符号双乘加)、SMUSD(有符号双乘减)

 

SMUAD 和 SMUSD
有符号双半字乘加与有符号双半字乘减

语法

 

其中:
• op 为以下指令之一:

  • SMUAD:有符号双半字乘加

  • SMUADX:有符号双半字乘加(半字交换)

  • SMUSD:有符号双半字乘减

  • SMUSDX:有符号双半字乘减(半字交换)

  • 若包含X,则执行"低半字×高半字"和"高半字×低半字"乘法

  • 若省略X,则执行"低半字×低半字"和"高半字×高半字"乘法
    • cond 为可选条件码(参见第65页"条件执行")
    • Rd 为目标寄存器
    • RnRm 为存放操作数的寄存器

操作

SMUAD指令 将操作数解释为两个有符号半字:

  1. 可选地交换第二操作数的半字顺序

  2. 执行两次有符号16×16位乘法

  3. 将两个乘法结果相加

  4. 将加法结果写入目标寄存器

SMUSD指令 将操作数值解释为有符号补码整数:

  1. 可选地交换第二操作数的半字顺序

  2. 执行两次有符号16×16位乘法

  3. 从低半字乘法结果中减去高半字乘法结果

  4. 将减法结果写入目标寄存器

限制条件

这些指令中:

  • 不得使用SP或PC寄存器

条件标志位

  • 若加法溢出则设置Q标志位(乘法操作不会产生溢出)

示例

 

 

SMUAD R0, R4, R5 ; 将R4低半字与R5低半字相乘,加上
; R4高半字与R5高半字的乘积,结果写入R0
SMUADX R3, R7, R4 ; 将R7低半字与R4高半字相乘,加上
; R7高半字与R4低半字的乘积,结果写入R3

3.6.10 SMUL(有符号乘法)、SMULW(有符号乘半字)

 

有符号乘法(半字)与有符号乘法(字×半字)

语法

 

 

op为以下指令之一:

  • SMUL(XY):有符号乘法(半字)

    • X和Y指定源寄存器Rn和Rm中用作乘数的半字:

      • X=B:使用Rn的底半字(位[15:0])

      • X=T:使用Rn的顶半字(位[31:16])

      • Y=B:使用Rm的底半字(位[15:0])

      • Y=T:使用Rm的顶半字(位[31:16])

  • SMULW(Y):有符号乘法(字×半字)

    • Y指定源寄存器Rm中用作第二个乘数的半字:

      • Y=B:使用Rm的底半字(位[15:0])

      • Y=T:使用Rm的顶半字(位[31:16])

  • cond为可选条件码(参见第65页"条件执行")

  • Rd为目标寄存器

  • RnRm为存放操作数的寄存器

操作

SMULBB/SMULTB/SMULBT/SMULTT指令
将Rn和Rm的值解释为四个有符号16位整数:

  1. 对Rn和Rm指定的有符号半字(顶/底)执行乘法

  2. 将32位乘法结果写入Rd

SMULWT/SMULWB指令
将Rn解释为32位有符号整数,Rm解释为两个16位有符号半字:

  1. 将第一个操作数与第二个操作数的顶半字(T后缀)或底半字(B后缀)相乘

  2. 将48位结果的最高有效32位写入目标寄存器

限制条件

不得使用SP或PC寄存器

示例

 

SMULBT R0, R4, R5 ; 将R4的低半字与R5的高半字相乘,结果写入R0

PM0214 Rev 10
STM32 Cortex-M4 指令集

SMULBB R0, R4, R5 ; 将R4的低半字与R5的低半字相乘,结果写入R0
SMULTT R0, R4, R5 ; 将R4的高半字与R5的高半字相乘,结果写入R0
SMULTB R0, R4, R5 ; 将R4的高半字与R5的低半字相乘,结果写入R0
SMULWT R4, R5, R3 ; 将R5与R3的高半字相乘,提取高32位并写入R4
SMULWB R4, R5, R3 ; 将R5与R3的低半字相乘,提取高32位并写入R4

3.6.11 UMULL(无符号长乘法)、UMLAL(无符号长乘累加)、SMULL(有符号长乘法)、SMLAL(有符号长乘累加)

 

32位操作数的有符号/无符号长乘法(可选累加),产生64位结果

语法

其中:
• op 为以下指令之一:

  • UMULL:无符号长乘法

  • UMLAL:无符号长乘法(带累加)

  • SMULL:有符号长乘法

  • SMLAL:有符号长乘法(带累加)
    • cond 为可选条件码(参见第65页"条件执行")
    • RdHi, RdLo 为目标寄存器,对于UMLAL和SMLAL也用于存放累加值
    • RnRm 为存放操作数的寄存器

操作

UMULL指令
将Rn和Rm的值解释为无符号整数:

  1. 对两数执行乘法运算

  2. 将结果的低32位存入RdLo,高32位存入RdHi

UMLAL指令
将Rn和Rm的值解释为无符号整数:

  1. 对两数执行乘法运算

  2. 将64位乘积与RdHi:RdLo中的无符号64位值相加

  3. 将累加结果写回RdHi和RdLo

SMULL指令
将Rn和Rm的值解释为二进制补码有符号整数:

  1. 对两数执行乘法运算

  2. 将结果的低32位存入RdLo,高32位存入RdHi

SMLAL指令
将Rn和Rm的值解释为二进制补码有符号整数:

  1. 对两数执行乘法运算

  2. 将64位乘积与RdHi:RdLo中的有符号64位值相加

  3. 将累加结果写回RdHi和RdLo

限制条件

使用这些指令时:
• 不可使用SP或PC寄存器
• RdHi和RdLo必须是不同的寄存器

条件标志位

这些指令不会影响条件码标志位

示例

UMULL    R0, R4, R5, R6  ; 无符号乘法:(R4,R0) = R5 × R6  
SMLAL    R4, R5, R3, R8  ; 有符号乘累加:(R5,R4) = (R5,R4) + R3 × R8  
 

3.6.12 SDIV(有符号除法)、UDIV(无符号除法)

 

SDIV 和 UDIV
有符号除法与无符号除法

语法

其中:

  • cond 为可选条件码(参见第65页"条件执行")

  • Rd 为目标寄存器。若省略,则目标寄存器为Rn

  • Rn 为被除数寄存器

  • Rm 为除数寄存器

操作

  • SDIV:对Rn中的有符号整数执行除以Rm值的运算

  • UDIV:对Rn中的无符号整数执行除以Rm值的运算

对于两条指令:

  • 若Rn值无法被Rm整除,结果向零取整

限制条件

  • 不可使用SP或PC寄存器

条件标志位

  • 这些指令不会改变标志位

示例

SDIV R0, R2, R4  ; 有符号除法:R0 = R2 / R4  
UDIV R8, R8, R1  ; 无符号除法:R8 = R8 / R1  

3.7 饱和指令

本节介绍饱和指令。

 

 

表30. 饱和指令

助记符简要描述参考
SSAT 有符号饱和 第126页的SSAT和USAT
SSAT16 有符号半字饱和 第127页的SSAT16和USAT16
USAT 无符号饱和 第126页的SSAT和USAT
USAT16 无符号半字饱和 第127页的SSAT16和USAT16
QADD 饱和加法 第128页的QADD和QSUB
QSUB 饱和减法 第128页的QADD和QSUB
QSUB16 饱和减法16位 第128页的QADD和QSUB
QASX 饱和加法与减法(带交换) 第129页的QASX和QSAX
QSAX 饱和减法与加法(带交换) 第129页的QASX和QSAX
QDADD 饱和双倍并加法 第130页的QDADD和QDSUB
QDSUB 饱和双倍并减法 第130页的QDADD和QDSUB
UQADD16 无符号饱和加法16位 第132页的UQADD和UQSUB
UQADDB 无符号饱和加法8位 第132页的UQADD和UQSUB
UQASX 无符号饱和加法与减法(带交换) 第131页的UQASX和UQSAX
UQSAX 无符号饱和减法与加法(带交换) 第131页的UQASX和UQSAX
UQSUB16 无符号饱和减法16位 第132页的UQADD和UQSUB
UQSUBB 无符号饱和减法8位 第132页的UQADD和UQSUB

对于有符号的nn位饱和操作,规则如下:

  • 如果待饱和的值小于-2n−12n1,则返回的结果为-2n−12n1;

  • 如果待饱和的值大于2n−1−12n11,则返回的结果为2n−1−12n11;

  • 否则,返回的结果与待饱和的值相同。

对于无符号的nn位饱和操作,规则如下:

  • 如果待饱和的值小于0,则返回的结果为0;

  • 如果待饱和的值大于2n−12n1,则返回的结果为2n−12n1;

  • 否则,返回的结果与待饱和的值相同。

如果返回的结果与待饱和的值不同,则称为饱和。如果发生饱和,指令会将APSR中的Q标志设置为1;否则,Q标志保持不变。要将Q标志清零为0,必须使用MSR指令,详见第187页的MSR

要读取Q标志的状态,可使用MRS指令,详见第186页的MRS

3.7.1 SSAT(有符号饱和) 和 USAT(无符号饱和)

 

有符号饱和和无符号饱和到任意位位置,可在饱和前进行可选移位操作。

语法

 

其中:  
* `op` 是以下之一:  
  - SSAT:将有符号值饱和到有符号范围。  
  - USAT:将有符号值饱和到无符号范围。  
* `cond` 是可选的条件码(参见第65页的“条件执行”)。  
* `Rd` 是目标寄存器。  
* `n` 指定饱和的位位置:  
  - 对于 SSAT,n 的范围是 1 到 32。  
  - 对于 USAT,n 的范围是 0 到 31。  
* `Rm` 是包含待饱和值的寄存器。  
* `shift #s` 是可选的在饱和前应用于 `Rm` 的移位操作,可以是以下之一:  
  - ASR #s:其中 s 的范围是 1 到 31(算术右移)。  
  - LSL #s:其中 s 的范围是 0 到 31(逻辑左移)。  

操作

这些指令将值饱和到有符号或无符号的 n 位范围。

  • SSAT 指令:先应用指定的移位,然后将值饱和到有符号范围:

    −2n−1≤x≤2n−1−12n1x2n11
  • USAT 指令:先应用指定的移位,然后将值饱和到无符号范围:

    0≤x≤2n−10x2n1

限制

  • 不能使用 SP(栈指针)和 PC(程序计数器)。

条件标志

  • 这些指令不会影响条件码标志(如 N、Z、C、V)。

  • 如果发生饱和,这些指令会将 Q 标志设置为 1。

示例

 

SSAT R7, #16, R7, LSL #4  ; 将 R7 中的值逻辑左移 4 位,然后  
                           ; 将其饱和为有符号 16 位值,并写回 R7  

USATNE R0, #7, R5          ; 条件性地将 R5 中的值饱和为无符号 7 位值,  
                           ; 并写入 R0  

3.7.2 SSAT16(有符号半字饱和) 和 USAT16(无符号半字饱和)

 

对两个半字(halfword)执行有符号或无符号饱和到指定位位置的操作。

语法

其中:

  • op 是以下之一:

    • SSAT16:将有符号半字值饱和到有符号范围。

    • USAT16:将有符号半字值饱和到无符号范围。

  • cond 是可选的条件码(参见第65页的“条件执行”)。

  • Rd 是目标寄存器。

  • n 指定饱和的位位置:

    • 对于 SSAT16,n 的范围是 1 到 16。

    • 对于 USAT16,n 的范围是 0 到 15。

  • Rm 是包含待饱和值的寄存器。

操作

  • SSAT16 指令:

    1. 对寄存器中两个有符号 16 位半字值,按 n 指定的位位置进行饱和处理。

    2. 将结果作为两个有符号 16 位半字写入目标寄存器。

  • USAT16 指令:

    1. 对寄存器中两个无符号 16 位半字值,按 n 指定的位位置进行饱和处理。

    2. 将结果作为两个无符号半字写入目标寄存器。

限制

  • 不能使用 SP(栈指针)和 PC(程序计数器)。

条件标志

  • 这些指令不会影响条件码标志(如 N、Z、C、V)。

  • 如果发生饱和,这些指令会将 Q 标志设置为 1。

示例

 

SSAT16 R7, #9, R2    ; 将 R2 中的高半字和低半字分别饱和为  
                      ; 9 位有符号值,并写入 R7 的对应半字  

USAT16NE R0, #13, R5 ; 条件性地将 R5 中的高半字和低半字  
                      ; 饱和为 13 位无符号值,并写入 R0 的对应半字  

3.7.3 QADD(饱和加法) 和 QSUB(饱和减法)

 

有符号饱和加法与饱和减法

语法

 

其中:

  • op 是以下之一:

    • QADD:32 位饱和加法

    • QADD8:四个 8 位整数的饱和加法

    • QADD16:两个 16 位整数的饱和加法

    • QSUB:32 位饱和减法

    • QSUB8:四个 8 位整数的饱和减法

    • QSUB16:两个 16 位整数的饱和减法

  • cond 是可选的条件码(参见第 65 页的“条件执行”)。

  • Rd 是目标寄存器。

  • Rn 和 Rm 是存放第一和第二操作数的寄存器。

操作

这些指令对两个、四个或八个值进行加法或减法运算,并将结果饱和到有符号范围后写入目标寄存器。

  • QADD 和 QSUB 指令执行加法或减法后,将结果饱和到有符号范围:

    −2n−1≤x≤2n−1−12n1x2n11

    其中,n 由指令的位数决定(32、16 或 8)。

如果返回的结果与待饱和的值不同,则称为饱和。如果发生饱和,QADD 和 QSUB 指令会将 APSR 中的 Q 标志设置为 1;否则,Q 标志保持不变。

  • 8 位和 16 位的 QADD 和 QSUB 指令 始终不改变 Q 标志。

要清除 Q 标志为 0,必须使用 MSR 指令(参见第 187 页的 MSR)。
要读取 Q 标志的状态,可使用 MRS 指令(参见第 186 页的 MRS)。

限制

  • 不能使用 SP(栈指针)和 PC(程序计数器)。

条件标志

    • 这些指令不会影响条件码标志(如 N、Z、C、V)。

    • 如果发生饱和,这些指令会将 Q 标志设置为 1。

示例

1. 饱和加法指令(16位半字)

QADD16 R7, R4, R2 ; 将寄存器R4和R2中的对应半字相加,
                  ; 结果饱和到16位有符号范围后,
                  ; 写入R7的对应半字

2. 饱和加法指令(8位字节)

QADD8 R3, R1, R6  ; 将寄存器R1和R6中的对应字节相加,
                  ; 结果饱和到8位有符号范围后,
                  ; 写入R3的对应字节

3. 饱和减法指令(16位半字)

QSUB16 R4, R2, R3 ; 从寄存器R2的半字中减去R3的对应半字,
                  ; 结果饱和到16位有符号范围后,
                  ; 写入R4的对应半字

4. 饱和减法指令(8位字节)

QSUB8 R4, R2, R5  ; 从寄存器R2的字节中减去R5的对应字节,
                  ; 结果饱和到8位有符号范围后,
                  ; 写入R4的对应字节

3.7.4 QASX(有符号半字交叉饱和加减) 和 QSAX(有符号半字交叉饱和减加)

 

带交换的饱和加减法与带交换的饱和减加法(有符号)

语法

 

其中:

  • op 是以下之一:

    • QASX:带交换的加法与减法并饱和

    • QSAX:带交换的减法与加法并饱和

  • cond 是可选的条件码(参见第65页的“条件执行”)

  • Rd 是目标寄存器

  • Rn 和 Rm 是存放操作数的寄存器

操作

QASX指令:

  1. 将第一个操作数的高半字与第二个操作数的低半字相加

  2. 从第一个操作数的低半字中减去第二个操作数的高半字

  3. 将减法结果饱和到16位有符号范围(-32768 ≤ x ≤ 32767),写入目标寄存器的低半字

  4. 将加法结果饱和到16位有符号范围(-32768 ≤ x ≤ 32767),写入目标寄存器的高半字

QSAX指令:

  1. 从第一个操作数的高半字中减去第二个操作数的低半字

  2. 将第一个操作数的低半字与第二个操作数的高半字相加

  3. 将加法结果饱和到16位有符号范围(-32768 ≤ x ≤ 32767),写入目标寄存器的低半字

  4. 将减法结果饱和到16位有符号范围(-32768 ≤ x ≤ 32767),写入目标寄存器的高半字

限制

  • 不能使用SP(栈指针)和PC(程序计数器)

条件标志

这些指令不会影响条件码标志

示例

 

1. QASX 指令(带交换的饱和加减法)

QASX R7, R4, R2   ; 将R4的高半字与R2的低半字相加,
                  ; 结果饱和到16位后写入R7的高半字;
                  ; 将R4的低半字减去R2的高半字,
                  ; 结果饱和到16位后写入R7的低半字

2. QSAX 指令(带交换的饱和减加法)

QSAX R0, R3, R5   ; 从R3的高半字中减去R5的低半字,
                  ; 结果饱和到16位后写入R0的高半字;
                  ; 将R3的低半字与R5的高半字相加,
                  ; 结果饱和到16位后写入R0的低半字
 

3.7.5 QDADD(双饱和加法) 和 QDSUB(双饱和减法)

 

有符号的饱和双倍加法与饱和双倍减法

语法

text
 
复制
 
下载
op{cond} {Rd}, Rm, Rn  

其中:

  • op 是以下之一:

    • QDADD:饱和双倍加法

    • QDSUB:饱和双倍减法

  • cond 是可选的条件码(参见第65页的“条件执行”)

  • Rd 是目标寄存器

  • Rn 和 Rm 是存放操作数的寄存器

操作

QDADD指令:

  1. 将第二个操作数(Rm)的值双倍化(乘以2)

  2. 将双倍化后的结果与第一个操作数(Rn)的值相加

  3. 将最终结果写入目标寄存器(Rd

QDSUB指令:

  1. 将第二个操作数(Rm)的值双倍化(乘以2)

  2. 从第一个操作数(Rn)的值中减去双倍化后的结果

  3. 将最终结果写入目标寄存器(Rd

饱和处理:

  • 双倍化和加法/减法的结果均饱和到32位有符号整数范围(−231≤x≤231−1231x2311)

  • 若任一操作(双倍化或加减法)发生饱和,则会将APSR中的Q标志置1

限制

  • 不能使用SP(栈指针)和PC(程序计数器)

条件标志

  • 若发生饱和,这些指令会将Q标志设置为1

示例

 

QDADD R7, R4, R2  ; 将R4的值双倍化并饱和到32位,  
                  ; 然后与R2相加,结果饱和到32位后写入R7  

QDSUB R0, R3, R5  ; 将R5的值双倍化并饱和到32位,  
                  ; 然后从R3中减去该值,结果饱和到32位后写入R0  

3.7.6 UQASX(无符号半字交叉饱和加减) 和 UQSAX(无符号半字交叉饱和减加)

 

无符号的带交换饱和加减法与带交换饱和减加法

语法

其中:

  • op 是以下之一:

    • UQASX:带交换的无符号饱和加减法

    • UQSAX:带交换的无符号饱和减加法

  • cond 是可选的条件码(参见第65页的"条件执行")

  • Rd 是目标寄存器

  • Rn 和 Rm 是存放操作数的寄存器

操作

UQASX指令:

  1. 将第一个操作数(Rn)的低半字与第二个操作数(Rm)的高半字相加

  2. 从第一个操作数(Rn)的高半字中减去第二个操作数(Rm)的低半字

  3. 将加法结果饱和到16位无符号范围(0 ≤ x ≤ 65535),写入目标寄存器(Rd)的高半字

  4. 将减法结果饱和到16位无符号范围(0 ≤ x ≤ 65535),写入目标寄存器(Rd)的低半字

UQSAX指令:

  1. 从第一个操作数(Rn)的高半字中减去第二个操作数(Rm)的低半字

  2. 将第一个操作数(Rn)的低半字与第二个操作数(Rm)的高半字相加

  3. 将减法结果饱和到16位无符号范围(0 ≤ x ≤ 65535),写入目标寄存器(Rd)的高半字

  4. 将加法结果饱和到16位无符号范围(0 ≤ x ≤ 65535),写入目标寄存器(Rd)的低半字

限制

  • 不能使用SP(栈指针)和PC(程序计数器)

条件标志

  • 这些指令不会影响条件码标志(N/Z/C/V)

示例

 

UQASX R7, R4, R2  ; 将R4的低半字与R2的高半字相加,  
                  ; 结果饱和到16位无符号数后写入R7的高半字;  
                  ; 从R4的高半字减去R2的低半字,  
                  ; 结果饱和到16位无符号数后写入R7的低半字  

UQSAX R0, R3, R5  ; 从R3的高半字减去R5的低半字,  
                  ; 结果饱和到16位无符号数后写入R0的高半字;  
                  ; 将R3的低半字与R5的高半字相加,  
                  ; 结果饱和到16位无符号数后写入R0的低半字  

3.7.7 UQADD(无符号饱和加法) 和 UQSUB(无符号饱和减法)

 

无符号饱和加法与减法

语法

 

其中:

  • op 是以下之一:

    • UQADD8:四个8位无符号整数的饱和加法

    • UQADD16:两个16位无符号整数的饱和加法

    • UQSUB8:四个8位无符号整数的饱和减法

    • UQSUB16:两个16位无符号整数的饱和减法

  • cond 是可选的条件码(参见第65页的"条件执行")

  • Rd 是目标寄存器

  • Rn 和 Rm 是存放操作数的寄存器

操作

UQADD16指令:

  1. 将第一个操作数(Rn)和第二个操作数(Rm)的对应高/低半字相加

  2. 将每个半字的加法结果饱和到16位无符号范围(0 ≤ x ≤ 65535)

UQADD8指令:

  1. 将第一个操作数(Rn)和第二个操作数(Rm)的四个对应字节相加

  2. 将每个字节的加法结果饱和到8位无符号范围(0 ≤ x ≤ 255)

UQSUB16指令:

  1. 从第一个操作数(Rn)的半字中减去第二个操作数(Rm)的对应半字

  2. 将每个半字的减法结果饱和到16位无符号范围(0 ≤ x ≤ 65535)

UQSUB8指令:

  1. 从第一个操作数(Rn)的字节中减去第二个操作数(Rm)的对应字节

  2. 将每个字节的减法结果饱和到8位无符号范围(0 ≤ x ≤ 255)

限制

  • 不能使用SP(栈指针)和PC(程序计数器)

条件标志

  • 这些指令不会影响条件码标志(N/Z/C/V)

示例

 

UQADD16 R7, R4, R2  ; 将R4和R2的对应半字相加,  
                    ; 结果饱和到16位无符号数后写入R7  

UQADD8 R4, R2, R5   ; 将R2和R5的对应字节相加,  
                    ; 结果饱和到8位无符号数后写入R4  

UQSUB16 R6, R3, R0  ; 从R3的半字中减去R0的对应半字,  
                    ; 结果饱和到16位无符号数后写入R6  

UQSUB8 R1, R5, R6   ; 从R5的字节中减去R6的对应字节,  
                    ; 结果饱和到8位无符号数后写入R1  

3.8 打包与解包指令

 表31 展示了用于数据打包与解包操作的指令:

 

助记符简要描述参考
PKH 半字打包 第135页的PKHBT和PKHTB
SXTAB 8位有符号扩展至32位并加法 第137页的SXTA和UXTA
SXTAB16 双8位有符号扩展至16位并加法 第137页的SXTA和UXTA
SXTAH 16位有符号扩展至32位并加法 第137页的SXTA和UXTA
SXTB 字节有符号扩展 第136页的SXT和UXT
SXTB16 双8位有符号扩展至16位 第136页的SXT和UXT
SXTH 半字有符号扩展 第136页的SXT和UXT
UXTAB 8位无符号扩展至32位并加法 第137页的SXTA和UXTA
UXTAB16 双8位无符号扩展至16位并加法 第137页的SXTA和UXTA
UXTAH 16位无符号扩展至32位并加法 第137页的SXTA和UXTA
UXTB 字节无符号扩展 第136页的SXT和UXT
UXTB16 双8位无符号扩展至16位 第136页的SXT和UXT
UXTH 半字无符号扩展 第136页的SXT和UXT

3.8.1 PKHBT(低位打包) 和 PKHTB(高位打包)

 

半字打包指令

语法

其中:

  • op 是以下之一:

    • PKHBT:半字打包(低位+高位带移位)

    • PKHTB:半字打包(高位+低位带移位)

  • cond 是可选的条件码(参见第65页的"条件执行")

  • Rd 是目标寄存器

  • Rn 是第一个操作数寄存器

  • Rm 是第二个操作数寄存器(可带移位操作)

  • imm 是移位长度,具体取决于指令类型:

    • PKHBT:LSL左移(1~31位,0表示不移位)

    • PKHTB:ASR算术右移(1~32位,32位移位编码为0b00000)

操作

PKHBT指令:

  1. 将第一个操作数(Rn)的低半字写入目标寄存器(Rd)的低半字

  2. 将第二个操作数(Rm)移位后的值写入目标寄存器(Rd)的高半字

PKHTB指令:

  1. 将第一个操作数(Rn)的高半字写入目标寄存器(Rd)的高半字

  2. 将第二个操作数(Rm)移位后的值写入目标寄存器(Rd)的低半字

限制

  • Rd 不能是栈指针(SP)或程序计数器(PC)

条件标志

  • 该指令不会改变任何状态标志

示例

 

PKHBT R3, R4, R5 LSL #0  ; 将R4的低半字写入R3的低半字,  
                          ; 将R5的高半字(不移位)写入R3的高半字  

PKHTB R4, R0, R2 ASR #1   ; 将R2算术右移1位后写入R4的低半字,  
                          ; 将R0的高半字写入R4的高半字  
 

3.8.2 SXT(有符号扩展) 和 UXT(无符号扩展)

 

有符号扩展与零扩展

语法

 

其中:

  • op 是以下之一:

    • SXTB:将8位值有符号扩展至32位

    • SXTH:将16位值有符号扩展至32位

    • SXTB16:将两个8位值有符号扩展至两个16位值

    • UXTB:将8位值零扩展至32位

    • UXTH:将16位值零扩展至32位

    • UXTB16:将两个8位值零扩展至两个16位值

  • cond 是可选的条件码(参见第65页的"条件执行")

  • Rd 是目标寄存器

  • Rm 是存放待扩展值的寄存器

  • ROR #n 是可选循环右移操作:

    • ROR #8:值右移8位

    • ROR #16:值右移16位

    • ROR #24:值右移24位

    • 若省略,则不进行移位

操作

这些指令执行以下步骤:

  1. Rm的值循环右移0、8、16或24位

  2. 从结果中提取指定位并进行扩展:

    • SXTB:提取位[7:0]并有符号扩展至32位

    • UXTB:提取位[7:0]并零扩展至32位

    • SXTH:提取位[15:0]并有符号扩展至32位

    • UXTH:提取位[15:0]并零扩展至32位

    • SXTB16:提取位[7:0]和位[23:16],分别有符号扩展至16位

    • UXTB16:提取位[7:0]和位[23:16],分别零扩展至16位

限制

  • 不能使用SP(栈指针)和PC(程序计数器)

条件标志

  • 这些指令不会影响任何状态标志

示例

 

SXTH R4, R6, ROR #16  ; 将R6的值循环右移16位,  
                      ; 提取结果的低半字并**有符号扩展**至32位,  
                      ; 写入R4  

UXTB R3, R10          ; 提取R10的最低字节,  
                      ; **零扩展**至32位后写入R3  

 

3.8.3 SXTA(有符号扩展并累加) 和 UXTA(无符号扩展并累加)

 

有符号/无符号扩展并加法指令

语法

其中:

  • op 是以下之一:

    • SXTAB:8位有符号扩展至32位并加法

    • SXTAH:16位有符号扩展至32位并加法

    • SXTAB16:双8位有符号扩展至16位并加法

    • UXTAB:8位无符号扩展至32位并加法

    • UXTAH:16位无符号扩展至32位并加法

    • UXTAB16:双8位无符号扩展至16位并加法

  • cond 是可选条件码(参见第65页"条件执行")

  • Rd 是目标寄存器

  • Rn 是第一操作数寄存器

  • Rm 是待移位扩展的寄存器

  • ROR #n 可选循环右移:

    • ROR #8:右移8位

    • ROR #16:右移16位

    • ROR #24:右移24位

    • 省略时不移位

操作流程

  1. 循环右移:将Rm的值右移0/8/16/24位

  2. 位提取与扩展:

    • SXTAB/UXTAB:提取位[7:0],有符号/零扩展至32位

    • SXTAH/UXTAH:提取位[15:0],有符号/零扩展至32位

    • SXTAB16/UXTAB16:

      • 提取位[7:0]和位[23:16]

      • 分别有符号/零扩展至16位

  3. 加法运算:将扩展后的值与Rn对应位相加,结果存入Rd

限制

  • 禁止使用 SP(栈指针)和 PC(程序计数器)

条件标志

  • 不影响任何状态标志

示例

 

SXTAH R4, R8, R6, ROR #16  ; 将R6循环右移16位,提取低半字  
                           ; 有符号扩展至32位后与R8相加,结果存入R4  

UXTAB R3, R4, R10          ; 提取R10最低字节,零扩展至32位  
                           ; 与R4相加后结果存入R3  

3.9 位域操作指令

 表32 展示了用于寄存器相邻位集合或位域操作的指令:

 

助记符功能描述参考章节
BFC 位域清零 第139页 BFC和BFI
BFI 位域插入 第139页 BFC和BFI
SBFX 有符号位域提取 第140页 SBFX和UBFX
SXTB 字节有符号扩展 第141页 SXT和UXT
SXTH 半字有符号扩展 第141页 SXT和UXT
UBFX 无符号位域提取 第140页 SBFX和UBFX
UXTB 字节零扩展 第141页 SXT和UXT
UXTH 半字零扩展 第141页 SXT和UXT

3.9.1 BFC(位段清零) 和 BFI(位段插入)

 

位域清零与位域插入

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器

  • Rn:源寄存器(仅BFI指令使用)

  • #lsb:位域最低有效位位置(0-31)

  • #width:位域宽度(1至32-lsb)

操作说明

  • BFC指令:
    清除目标寄存器中指定的位域。将Rd寄存器从lsb位开始的连续width位清零,其他位保持不变。

  • BFI指令:
    将源寄存器的位域插入目标寄存器。用Rn寄存器从第0位开始的width位,替换Rd寄存器中从lsb位开始的width位,其他位保持不变。

使用限制

  • 禁止使用 SP(栈指针)和 PC(程序计数器)

条件标志

  • 这些指令不会影响任何状态标志

应用示例

 

 
BFC R5, #8, #12    ; 将R5的第8至19位(共12位)清零  
                   ; 其他位保持不变  

BFI R9, R2, #8, #12 ; 将R2的第0至11位复制到R9的第8至19位  
                   ; R9的其他位保持不变  

3.9.2 SBFX(有符号位段提取) 和 UBFX(无符号位段提取)

 

有符号位域提取与无符号位域提取

语法

 

参数说明:

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器(32位)

  • Rn:源寄存器

  • #lsb:位域最低有效位位置(0-31)

  • #width:位域宽度(1至32-lsb)

操作说明

  • SBFX指令:

    1. Rn中提取lsb位开始的width

    2. 有符号扩展至32位

    3. 结果写入Rd

  • UBFX指令:

    1. Rn中提取lsb位开始的width

    2. 零扩展至32位

    3. 结果写入Rd

使用限制

  • 禁止使用 SP(栈指针)和 PC(程序计数器)

条件标志

  • 这些指令不会影响任何状态标志

应用示例

 

SBFX R0, R1, #20, #4  ; 提取R1的第20-23位(4位)  
                      ; 有符号扩展至32位后写入R0  

UBFX R8, R11, #9, #10 ; 提取R11的第9-18位(10位)  
                      ; 零扩展至32位后写入R8  

3.9.3 SXT(有符号扩展) 和 UXT(无符号扩展)

 

有符号扩展与零扩展

语法

 

参数说明:

  • extend 扩展类型:

    • B:8位值扩展至32位

    • H:16位值扩展至32位

  • cond:可选条件码(参见第65页"条件执行")

  • Rd:目标寄存器(可省略,默认为Rm)

  • Rm:待扩展值的源寄存器

  • ROR #n:可选循环右移(8/16/24位)

操作流程

  1. 循环右移(可选):

    • Rm的值右移8/16/24位

  2. 位提取与扩展:

    • SXTB:提取位[7:0] → 有符号扩展至32位

    • UXTB:提取位[7:0] → 零扩展至32位

    • SXTH:提取位[15:0] → 有符号扩展至32位

    • UXTH:提取位[15:0] → 零扩展至32位

使用限制

  • 禁止使用 SP(栈指针)和 PC(程序计数器)

条件标志

  • 不影响任何状态标志

应用示例

 

SXTH R4, R6, ROR #16  ; 1. 将R6循环右移16位  
                      ; 2. 提取结果的低16位  
                      ; 3. 有符号扩展至32位后写入R4  

UXTB R3, R10          ; 1. 提取R10的最低字节(不移位)  
                      ; 2. 零扩展至32位后写入R3  

3.9.4 分支与控制指令

 

 

助记符功能描述参考章节
B 无条件分支 第142页 B/BL/BX/BLX
BL 带链接的分支(保存返回地址) 第142页 B/BL/BX/BLX
BLX 带链接的间接分支 第142页 B/BL/BX/BLX
BX 间接分支 第142页 B/BL/BX/BLX
CBNZ 非零比较分支 第144页 CBZ/CBNZ
CBZ 零值比较分支 第144页 CBZ/CBNZ
IT 条件执行块(If-Then) 第145页 IT指令
TBB 字节查表分支 第147页 TBB/TBH
TBH 半字查表分支 第147页 TBB/TBH

3.9.5 B(分支)、BL(带链接分支)、BX(分支交换) 和 BLX(带链接分支交换)

 分支指令

语法

 

其中:

  • “B”表示分支(立即寻址)。

  • “BL”表示带链接的分支(立即寻址)。

  • “BX”表示间接分支(寄存器寻址)。

  • “BLX”表示带链接的间接分支(寄存器寻址)。

  • “cond”为可选条件码,详见第65页的“条件执行”部分。

  • “label”为PC相对表达式,参见第65页的“PC相对表达式”说明。

  • “Rm”为寄存器,用于指定分支目标地址。Rm值的B[i][0]位必须为1,但实际分支目标地址需通过将该位改为0生成。

操作

这些指令均会跳转至 label(标签)或 Rm 寄存器指定的地址。此外:

  • BL 和 BLX 指令会将下一条指令的地址写入 LR(链接寄存器,即 R14)。

  • 若 Rm 的 bit[0] 为 0,BX 和 BLX 指令会触发 UsageFault 异常。


条件分支的特殊规则

  • cond label 是唯一既可在 IT 块内也可在 IT 块外使用的条件分支指令。

  • 其他所有分支指令在 IT 块内必须为条件指令,在 IT 块外则必须为无条件指令(详见第 145 页的 IT 指令说明)。

表 34. 分支跳转范围

 

指令跳转范围
B label ~16 MB 至 +16 MB
Bcond label(IT 块外) ~1 MB 至 +1 MB
Bcond label(IT 块内) ~16 MB 至 +16 MB
BL(cond) label ~16 MB 至 +16 MB
BX(cond) Rm 寄存器中的任意值
BLX(cond) Rm 寄存器中的任意值

注:为达到最大跳转范围,可能需要使用 .W 后缀(详见第 68 页的指令宽度选择部分)。

 

限制条件

使用分支指令时需遵守以下限制:

  • BLX 指令中禁止使用 PC(程序计数器)。

  • 对于 BX 和 BLX 指令,Rm 的 bit[0] 必须为 1 以确保正确执行,但实际跳转的目标地址需将 bit[0] 改为 0。

  • 若这些指令位于 IT 块内,则必须作为 IT 块的最后一条指令。

B 指令是唯一无需强制位于 IT 块内的条件分支指令,但在 IT 块内使用时,其跳转范围更大。

条件标志位

这些指令不会改变处理器的标志位。

示例

 

 
B loopA          ; 跳转至 loopA  
BLE ng           ; 条件跳转至标签 ng(若满足条件 LE)  
B.W target       ; 跳转至 target(16MB 范围内)  
BEQ target      ; 条件跳转至 target(若满足条件 EQ)  
BEQ.W target    ; 条件跳转至 target(1MB 范围内)  
BL func          ; 带链接跳转(调用函数 func),返回地址存入 LR  
BX LR            ; 从函数调用返回  
BXNE R0          ; 条件跳转至 R0 中存储的地址(若满足条件 NE)  
BLX R0           ; 带链接的间接跳转(调用 R0 中存储的地址)  

3.9.6 CBZ(为零跳转) 和 CBNZ(非零跳转)

 

零比较跳转与非零比较跳转

语法

参数说明:

  • Rn:存放操作数的寄存器。

  • label:跳转目标地址。

功能

CBZ 和 CBNZ 指令可在不改变条件标志位的前提下实现条件跳转,减少指令数量。

  • CBZ Rn, label 功能等价于(但不影响标志位):

    CMP Rn, #0  
    BEQ label  
  • CBNZ Rn, label 功能等价于(但不影响标志位):

    CMP Rn, #0  
    BNE label  

限制条件

  • Rn 必须为 R0~R7 范围内的寄存器。

  • 跳转目标地址必须在指令后 4~130 字节范围内。

  • 禁止在 IT 块内使用这两条指令。

条件标志位

这些指令不会改变处理器的标志位。

示例

 

 
CBZ R5, target   ; 若 R5 为 0,则向前跳转至 target  
CBNZ R0, target  ; 若 R0 不为 0,则向前跳转至 target  
 

3.9.7 IT(条件执行块)

 

If-Then 条件执行指令

语法

 

参数说明:

  • x:指定 IT 块中第二条指令的条件开关(T 或 E)。

  • y:指定 IT 块中第三条指令的条件开关(T 或 E)。

  • z:指定 IT 块中第四条指令的条件开关(T 或 E)。

  • cond:指定 IT 块中第一条指令的条件(如 EQNE 等)。

条件开关选项:

  • T(Then):应用与 cond 相同的条件。

  • E(Else):应用 cond 的相反条件。

特殊规则:
若 cond 为 AL(无条件执行),则 IT 块内所有指令必须为无条件指令,且 xyz 只能为 T 或省略(不可为 E)。

功能

  • IT 指令将后续 1~4 条指令转换为条件执行指令,形成 IT 块。

  • IT 块内指令的条件可以是相同或逻辑相反的(通过 T/E 指定)。

  • IT 块内的每条指令(包括分支指令)必须在其语法中显式指定 {cond} 条件。

  • BKPT 指令在 IT 块内始终执行(即使条件不满足)。

汇编器支持:
部分汇编器可自动生成所需的 IT 指令,无需手动编写(详见具体汇编器文档)。

异常处理

  • 异常可在 IT 指令与 IT 块之间或 IT 块内部触发,此时处理器会进入异常处理程序,并在 LR 和堆栈的 PSR 中保存正确的返回信息。

  • 通过异常返回指令(如 BX LR)可正常恢复执行,继续处理 IT 块。

    注:这是唯一允许通过修改 PC 跳转至 IT 块内指令的场景。

限制条件

IT 块内禁止使用以下指令:

    • IT(嵌套 IT 指令)。

    • CBZ 和 CBNZ(零比较跳转指令)。

    • CPSID 和 CPSIE(中断屏蔽指令)。

IT 块的其他限制条件

1. 分支与 PC 修改指令的限制

  • 禁止在 IT 块内部使用分支或修改 PC 的指令,除非它们是 IT 块的最后一条指令。
    受影响的指令包括:

    • ADD PC, PC, Rm

    • MOV PC, Rm

    • BBLBXBLX

    • 任何写入 PC 的 LDMLDR 或 POP 指令

    • TBB 和 TBH

  • 禁止跳转至 IT 块内的指令(异常返回除外)。

2. 条件指令的规则

  • 除 B{cond} 外,所有条件指令必须位于 IT 块内。

    • B{cond} 可位于 IT 块内外,但在 IT 块内时跳转范围更大。

  • IT 块内每条指令的条件后缀必须与其他指令的条件相同或逻辑相反。

3. 汇编器额外限制

部分汇编器可能禁止在 IT 块内使用汇编伪指令(如宏或数据定义)。

条件标志位

IT 指令不会改变处理器的标志位。


示例

 

示例 1:ITTE 块(3 条件指令)

 
ITTE NE          ; 后续 3 条指令为条件执行  
ANDNE R0, R0, R1 ; ANDNE 不更新标志位  
ADDSNE R2, R2, #1 ; ADDSNE 更新标志位  
MOVEQ R2, R3     ; 条件移动(EQ 是 NE 的反条件)  

示例 2:ITE 块(2 条件指令)

CMP R0, #9       ; 将 R0 的十六进制值(0~15)转换为 ASCII  
ITE GT           ; 后续 2 条指令为条件执行  
ADDGT R1, R0, #55 ; 0xA~0xF → 'A'~'F'  
ADDLE R1, R0, #48 ; 0x0~0x9 → '0'~'9'  

示例 3:IT 块(单条件指令)

IT GT            ; 仅 1 条条件指令  
ADDGT R1, R1, #1 ; 条件递增 R1  

示例 4:ITTEE 块(4 条件指令)

ITTEE EQ         ; 后续 4 条指令为条件执行  
MOVEQ R0, R1     ; 条件移动  
ADDEQ R2, R2, #10 ; 条件加法  
ANDNE R3, R3, #1 ; 条件 AND(NE 是 EQ 的反条件)  
BNE.W dloop      ; 分支指令必须为 IT 块的最后一条指令  

错误示例:缺少条件后缀

IT NE            ; 下一条指令应为条件指令  
ADD R0, R0, R1   ; 语法错误:IT 块内指令未指定条件后缀  

3.9.8 TBB(表跳转字节) 和 TBH(表跳转半字)

 

字节表跳转与半字表跳转

语法

 

参数说明:

  • Rn 是包含分支长度表地址的寄存器。
    如果 Rn 是 PC,则表的地址为紧跟在 TBB 或 TBH 指令后的字节地址。

  • Rm 是索引寄存器,包含表中的索引值。对于半字表,LSL #1 会将 Rm 中的值翻倍,以形成表中的正确偏移量。

操作

这些指令使用单字节偏移表(TBB)或半字偏移表(TBH)实现 PC 相对前向分支。Rn 提供指向表的指针,Rm 提供表中的索引值。对于 TBB,分支偏移量为表中返回的无符号字节值的两倍;对于 TBH,分支偏移量为表中返回的无符号半字值的两倍。分支跳转的目标地址为:紧跟在 TBB 或 TBH 指令后的字节地址加上该偏移量。

限制条件

  • Rn 不能为 SP(栈指针)。

  • Rm 不能为 SP 或 PC。

  • 在 IT 块内使用时,必须作为最后一条指令。

条件标志位

这些指令不会改变处理器的标志位。


示例

 

1. TBB 字节表跳转

ADR.W R0, BranchTable_Byte  ; 加载跳转表基址到 R0  
TBB [R0, R1]                ; 根据 R1 的索引跳转  

; 各分支标签  
Case1:  
    ; 指令序列  
Case2:  
    ; 指令序列  
Case3:  
    ; 指令序列  

; 跳转表定义(字节偏移量)  
BranchTable_Byte:  
    DCB 0                    ; Case1 偏移量(0 ×2 = 0,跳转到 Case1)  
    DCB ((Case2 - Case1)/2)  ; Case2 偏移量(相对 Case1 的字节差 ÷2)  
    DCB ((Case3 - Case1)/2)  ; Case3 偏移量  

2. TBH 半字表跳转

TBH [PC, R1, LSL #1]        ; 使用 PC 作为表基址,R1 索引 ×2  

; 跳转表定义(半字偏移量)  
BranchTable_H:  
    DCI ((CaseA - BranchTable_H)/2)  ; CaseA 偏移量  
    DCI ((CaseB - BranchTable_H)/2)  ; CaseB 偏移量  
    DCI ((CaseC - BranchTable_H)/2)  ; CaseC 偏移量  

; 各分支标签  
CaseA:  
    ; 指令序列  
CaseB:  
    ; 指令序列  
CaseC:  
    ; 指令序列  

3.10 浮点指令

(前置说明)本指令集仅在系统包含并启用浮点运算单元(FPU)时可用。关于FPU启用方法,请参见第257页"启用浮点运算单元"章节。

 

助记符功能描述详细说明页数
VABS 浮点绝对值运算 第151页 VABS
VADD 浮点加法运算 第152页 VADD
VCMP 浮点寄存器比较(或与零值比较) 第153页 VCMP/VCMPE
VCMPE 带无效操作检查的浮点比较 第153页 VCMP/VCMPE
VCVT 浮点与整型转换 第154页 VCVT/VCVTR
VCVT 浮点与定点数转换 第155页 浮点-定点转换
VCVTR 带舍入的浮点-整型转换 第154页 VCVT/VCVTR
VCVTB 半精度转单精度 第156页 VCVTB/VCVTT
VCVTT 单精度转半精度 第156页 VCVTB/VCVTT
VDIV 浮点除法运算 第157页 VDIV
VFMA 浮点融合乘加运算 第158页 VFMA/VFMS
VFNMA 浮点融合负乘加运算 第159页 VFNMA/VFNMS
VFMS 浮点融合乘减运算 第158页 VFMA/VFMS
VFNMS 浮点融合负乘减运算 第159页 VFNMA/VFNMS
VLDM 扩展寄存器批量加载 第160页 VLDM
VLDR 内存到扩展寄存器的单次加载 第161页 VLDR
VLMA 浮点乘加运算 第162页 VLMA/VLMS
VLMS 浮点乘减运算 第162页 VLMA/VLMS
VMOV 浮点立即数传输 第163页 立即数传输
VMOV 浮点寄存器间传输 第164页 寄存器传输
VMOV ARM核心寄存器→单精度标量 第165页 标量传输
VMOV 双ARM寄存器→双单精度 第166页 寄存器到单精度
VMOV ARM寄存器与标量间传输 第167页 双寄存器传输
VMOV 标量→ARM核心寄存器 第168页 标量到寄存器
VMRS 浮点系统寄存器→ARM核心寄存器 第169页 VMRS

 

助记符功能描述详细说明页数
VMSR ARM核心寄存器→浮点系统寄存器传输 第170页 VMSR
VMUL 浮点乘法运算 第171页 VMUL
VNEG 浮点取负运算 第172页 VNEG
VNMLA 浮点乘加运算(带取负) 第173页 VNMLA/VNMLS/VNMUL
VNMLS 浮点乘减运算(带取负) 第173页 VNMLA/VNMLS/VNMUL
VNMUL 浮点乘法运算(带取负) 第173页 VNMLA/VNMLS/VNMUL
VPOP 扩展寄存器出栈操作 第174页 VPOP
VPUSH 扩展寄存器入栈操作 第175页 VPUSH
VSQRT 浮点平方根运算 第176页 VSQRT
VSTM 扩展寄存器批量存储 第177页 VSTM
VSTR 扩展寄存器→内存单次存储 第178页 VSTR
VSUB 浮点减法运算 第179页 VSUB

3.10.1 VABS(浮点绝对值)

浮点绝对值运算

语法

 

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Sd:目标浮点寄存器

  • Sm:操作数浮点寄存器

操作流程

  1. 计算操作数寄存器(Sm)中浮点数值的绝对值

  2. 将结果存入目标寄存器(Sd)

使用限制

本指令无特殊使用限制

浮点状态标志

  • 符号位(sign bit)强制清零

应用示例

 

VABS.F32 S4, S6 ; 计算S6寄存器的绝对值,结果存入S4

 

3.10.2 VADD(浮点加法)

浮点加法指令

语法

 

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Sd:目标浮点寄存器(可省略,默认为Sn)

  • Sn, Sm:操作数浮点寄存器

操作原理

  1. 对两个操作数寄存器(Sn与Sm)执行单精度浮点加法运算

  2. 运算结果存入目标寄存器(Sd)

使用限制

本指令无特殊架构限制

浮点状态标志

该指令不影响任何状态标志位

典型应用

 

VADD.F32 S4, S6, S7 ; 计算S6+S7,结果存入S4

3.10.3 VCMP(浮点比较), VCMPE(带异常的浮点比较)

3.10.3 VCMP/VCMPE

浮点比较指令

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • E:

    • 存在时:任何NaN操作数触发无效操作异常

    • 不存在时:仅信号型NaN触发异常

  • Sd:待比较浮点寄存器

  • Sm:比较基准浮点寄存器(或立即数0.0)

操作特性

  1. 支持两种比较模式:

    • 两个浮点寄存器间比较

    • 浮点寄存器与零值比较

  2. 比较结果写入浮点状态控制寄存器(FPSCR)标志位

异常触发

  • 任意操作数为NaN时可能触发无效操作异常

  • 操作数为信号型NaN时必定触发异常

标志位传递

需配合VMRS指令(第169页)将FPSCR标志位传输至ARM状态寄存器

应用示例

VCMP.F32 S4, #0.0 ; S4寄存器与零值比较
VCMP.F32 S4, S2 ; S4与S2寄存器比较

3.10.4 VCVT(浮点与整数转换), VCVTR(浮点与整数舍入转换)

浮点与整型转换指令

语法

参数说明:

  • R:

    • 存在时:采用FPSCR指定的舍入模式

    • 不存在时:采用"向零舍入"模式(仅浮点转整型时生效)

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Tm:数据类型标识符:

    • S32:有符号32位整型

    • U32:无符号32位整型

  • Sd/Sm:目标寄存器/操作数寄存器

转换方向

  1. 浮点→整型转换(.F32.Tm语法):

    • 默认采用向零舍入

    • 带R后缀时采用FPSCR舍入模式

  2. 整型→浮点转换(.Tm.F32语法):

    • 强制采用FPSCR舍入模式

技术特性

  • 转换结果存入目标寄存器Sd

  • 整型转换范围:32位有符号/无符号数值

状态标志

本指令不影响任何状态标志位

3.10.5 VCVT(浮点与定点转换)

浮点与定点数转换指令

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Td:定点数数据类型:

    • S16:有符号16位

    • U16:无符号16位

    • S32:有符号32位

    • U32:无符号32位

  • Sd:目标寄存器和操作数寄存器

  • fbits:定点数小数位宽:

    • 16位类型:0-16位

    • 32位类型:1-32位

转换特性

  1. 浮点→定点转换(.F32.Td语法):

    • 采用"向零舍入"模式

    • 有符号类型执行符号扩展

    • 无符号类型执行零扩展

  2. 定点→浮点转换(.Td.F32语法):

    • 采用"就近舍入"模式

    • 仅使用源寄存器的低位有效位

技术规范

  • 浮点精度:单精度(.F32)

  • 定点数范围:16/32位有符号/无符号

  • 小数位宽动态可调(fbits参数)

状态标志

本指令不影响任何状态标志位

3.10.6 VCVTB(底部半精度转换), VCVTT(顶部半精度转换)

半精度与单精度浮点转换指令

语法

 

参数说明:

  • y:操作数区域选择位:

    • B:使用寄存器低16位([15:0])

    • T:使用寄存器高16位([31:16])

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Sd:目标寄存器

  • Sm:操作数寄存器

转换操作

  1. 半精度→单精度转换(.F16.F32后缀):

    • 从Sm寄存器指定区域(高/低16位)提取半精度值

    • 转换为单精度浮点数后存入Sd寄存器

  2. 单精度→半精度转换(.F32.F16后缀):

    • 将Sm寄存器单精度值转换为半精度

    • 结果写入Sd寄存器指定区域(高/低16位),保留另一区域原始值

技术特性

  • 支持寄存器高低位选择(通过B/T后缀)

  • 半精度浮点符合IEEE 754标准

  • 转换过程保持非目标区域数据不变

状态标志

本指令不影响任何状态标志位

3.10.7 VDIV(浮点除法)

浮点除法指令

语法

 

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Sd:目标寄存器(可省略,默认为Sn)

  • Sn:被除数寄存器

  • Sm:除数寄存器

运算规则

  1. 执行单精度浮点除法运算:Sn ÷ Sm

  2. 运算结果存入目标寄存器Sd

限制

无限制

状态标志

本指令不影响任何状态标志位

3.10.8 VFMA(浮点乘加), VFMS(浮点乘减)

浮点融合乘加/乘减指令

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Sd:目标寄存器(可省略,默认为Sn)

  • Sn/Sm:操作数寄存器

运算流程

VFMA指令:

  1. 执行单精度浮点乘法:Sn × Sm

  2. 将乘积与Sd值累加(不进行中间舍入)

VFMS指令:

  1. 对Sn操作数取负

  2. 执行单精度浮点乘法:-Sn × Sm

  3. 将乘积与Sd值相加(不进行中间舍入)

技术特性

  • 采用融合乘加运算(FMA)架构

  • 中间结果不单独舍入,提高计算精度

  • 符合IEEE 754-2008标准

状态标志

本指令不影响任何状态标志位

3.10.9 VFNMA(浮点负乘加), VFNMS(浮点负乘减)

浮点融合负乘加/乘减指令

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Sd:目标寄存器(可省略,默认为Sn)

  • Sn/Sm:操作数寄存器

运算流程

VFNMA指令:

  1. 对第一操作数取负:-Sn

  2. 执行单精度浮点乘法:-Sn × Sm

  3. 将目标寄存器值取负后与乘积相加:-Sd + (-Sn × Sm)

  4. 结果存入目标寄存器

VFNMS指令:

  1. 执行单精度浮点乘法:Sn × Sm

  2. 将目标寄存器值取负后与乘积相加:-Sd + (Sn × Sm)

  3. 结果存入目标寄存器

技术特性

  • 采用融合运算架构(不进行中间结果舍入)

  • 支持单精度浮点运算(.F32)

  • 符合IEEE 754-2008标准

状态标志

本指令不影响任何状态标志位

3.10.10 VLDM(浮点多寄存器加载)

浮点多寄存器加载指令

语法

参数说明:

  • mode 寻址模式:

    • IA(Increment After):从Rn指定地址开始顺序加载

    • DB(Decrement Before):在Rn指定地址前结束加载

  • cond:可选条件码(参见第65页条件执行章节)

  • size:可选数据位宽(32/64位)

  • Rn:基址寄存器(可使用SP堆栈指针)

  • !:回写标志(DB模式必须启用,IA模式可选)

  • list:目标寄存器列表(需用花括号包裹的连续编号寄存器,如{S0-S3})

操作特性

  • 从基址寄存器指定的连续内存地址加载多个浮点寄存器

  • 支持单精度(32位)/双精度(64位)数据加载

使用限制

  1. 数据位宽必须与寄存器类型匹配:

    • 32位对应单精度寄存器

    • 64位对应双精度寄存器

  2. 寄存器列表限制:

    • 至少包含1个寄存器

    • 双精度寄存器最多16个

  3. DB模式必须启用地址回写(!标志)

状态标志

本指令不影响任何状态标志位

3.10.11 VLDR(浮点单寄存器加载)

浮点单寄存器加载指令

语法

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • .64/.32:数据位宽标识符(双精度/单精度)

  • Dd:双精度目标寄存器

  • Sd:单精度目标寄存器

  • Rn:基址寄存器(支持SP堆栈指针)

  • imm:立即数偏移量(取值范围0-1020的4的倍数)

  • label:字面量数据标签

操作特性

  • 从内存加载单个浮点寄存器

  • 支持三种寻址模式:

    1. 基址寄存器+偏移量

    2. 字面量直接加载

    3. PC相对寻址

技术规范

  • 立即数偏移量需4字节对齐(imm%4=0)

  • 支持正负偏移(±1020范围内)

  • 双精度操作使用D寄存器,单精度使用S寄存器

状态标志

本指令不影响任何状态标志位

3.10.12 VLMA(浮点乘加加载), VLMS(浮点乘减加载)

 

浮点乘加/乘减指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Sd:目标寄存器(同时作为累加操作数)

  • Sn/Sm:乘法操作数寄存器

运算逻辑

VLMA指令:

  1. 执行单精度浮点乘法:Sn × Sm

  2. 将乘积与Sd寄存器值相加:Sd + (Sn × Sm)

VLMS指令:

  1. 执行单精度浮点乘法:Sn × Sm

  2. 从Sd寄存器值减去乘积:Sd - (Sn × Sm)

技术特性

  • 支持单精度浮点运算(.F32后缀)

  • 符合IEEE 754标准

  • 目标寄存器同时作为输入/输出操作数

状态标志

本指令不影响任何状态标志位

3.10.13 VMOV(立即数浮点传输)

 

浮点立即数传输指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Sd:目标浮点寄存器

  • #imm:浮点型立即数常量

操作特性

  • 将指定的浮点立即数加载到目标寄存器

  • 支持单精度浮点格式(.F32)

技术规范

  • 立即数必须符合IEEE 754单精度浮点格式

  • 支持条件执行

状态标志

本指令不影响任何状态标志位

3.10.14 VMOV(寄存器间浮点传输)

 

浮点寄存器间数据传输指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Dd/Dm:双精度目标/源寄存器(64位)

  • Sd/Sm:单精度目标/源寄存器(32位)

操作特性

  • 实现浮点寄存器间的数据直接拷贝

  • 支持双精度(.F64)和单精度(.F32)格式

技术规范

  • 源寄存器与目标寄存器位宽必须匹配

  • 支持条件执行

状态标志

本指令不影响任何状态标志位

3.10.15 VMOV(标量到Arm核寄存器传输)

双精度浮点寄存器分段传输指令

语法

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Rt:目标ARM核心寄存器(禁止PC/SP)

  • Dn:源双精度浮点寄存器(64位)

  • x:数据段选择位:

    • 0:传输低32位(Dn[31:0])

    • 1:传输高32位(Dn[63:32])

操作特性

  • 实现双精度浮点寄存器的分段传输

  • 支持高低位选择(通过x参数控制)

  • 数据从浮点单元传输至核心寄存器组

使用限制

  • 目标寄存器禁止为程序计数器(PC)或堆栈指针(SP)

状态标志

本指令不影响任何状态标志位

3.10.16 VMOV(Arm核寄存器到单精度传输)

 

语法格式

 

参数说明

  • cond:可选条件执行码(详见第65页条件执行章节)

  • Sn:32位单精度浮点寄存器

  • Rt:ARM核心通用寄存器(不可使用PC或SP)

功能特性

  1. 实现ARM核心寄存器与浮点单元间的数据双向传输

  2. 支持条件执行(通过cond参数控制)

  3. 数据格式为IEEE 754单精度浮点数

重要约束

  • 禁止使用程序计数器(PC)和堆栈指针(SP)作为目标寄存器

状态标志影响

本指令执行不会改变任何状态标志位

3.10.17 VMOV(双Arm核寄存器到双单精度传输)

 

语法规范

 

关键参数

  • cond:可选条件码(参见第65页条件执行

  • Sm/Sm+1:连续编号的单精度寄存器对

  • Rt/Rt2:ARM核心寄存器(允许非连续编号)

操作特性

  1. 实现两组寄存器间的批量数据传输:

    • 模式1:浮点寄存器对→核心寄存器对

    • 模式2:核心寄存器对→浮点寄存器对

  2. 支持条件执行

重要约束

  1. 浮点寄存器必须连续编号(Sm+1自动关联)

  2. 核心寄存器允许任意组合(无需连续)

  3. 禁止使用PC/SP作为目标寄存器

状态标志

本指令执行不影响处理器状态标志

3.10.18 VMOV(Arm核寄存器到标量传输)

 

核心寄存器到双精度浮点寄存器的分段传输指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • .32:可选数据位宽标识符(固定32位传输)

  • Dd[x]:目标双精度寄存器段选择:

    • 0:写入低32位(Dd[31:0])

    • 1:写入高32位(Dd[63:32])

  • Rt:源ARM核心寄存器(禁止PC/SP)

操作特性

  • 将核心寄存器的32位数据写入双精度浮点寄存器的指定区段

  • 非目标区段数据保持不变

技术限制

  • 源寄存器禁止为程序计数器(PC)或堆栈指针(SP)

  • 必须严格遵循32位对齐传输

状态标志

本指令不影响任何处理器状态标志

3.10.19 VMRS(浮点状态寄存器到Arm核寄存器传输)

 

浮点系统寄存器到ARM核心寄存器的传输指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Rt:目标核心寄存器(R0-R14,禁止PC/SP)

  • FPSCR:浮点状态与控制寄存器(源寄存器)

  • APSR_nzcv:应用程序状态寄存器标志位组

操作模式

  1. 寄存器传输模式:

    • 完整复制FPSCR寄存器值到目标通用寄存器

  2. 标志位传输模式:

    • 选择性同步FPSCR的N/Z/C/V标志到APSR

技术限制

  • 目标寄存器禁止为PC或SP

  • 标志位传输仅影响APSR的N/Z/C/V位

状态标志影响

  • 寄存器传输模式:不影响任何标志位

  • 标志位传输模式:更新APSR的N/Z/C/V标志

3.10.20 VMSR(Arm核寄存器到浮点状态寄存器传输)

 

ARM核心寄存器到浮点系统寄存器的传输指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • FPSCR:目标浮点状态与控制寄存器

  • Rt:源通用寄存器(R0-R14,禁止PC/SP)

操作特性

  • 将核心寄存器的32位数据传输至FPSCR寄存器

  • 完整覆盖FPSCR所有控制位和状态位

技术限制

  • 源寄存器禁止使用程序计数器(PC)或堆栈指针(SP)

  • 数据传输过程不可逆

状态更新

  • 更新FPSCR寄存器的内容

3.10.21 VMUL(浮点乘法)

 

浮点乘法指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Sd:目标寄存器(可省略,默认为Sn)

  • Sn/Sm:乘数操作数寄存器

运算规则

  1. 执行单精度浮点乘法运算:Sn × Sm

  2. 运算结果存入目标寄存器Sd

技术特性

  • 符合IEEE 754单精度浮点运算标准

  • 支持条件执行

  • 目标寄存器可选(缺省时替换首个操作数)

状态标志

本指令不影响任何状态标志位

3.10.22 VNEG(浮点取负)

 

浮点取负指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Sd:目标浮点寄存器

  • Sm:源浮点操作数寄存器

运算逻辑

  1. 对源寄存器(Sm)的浮点数值执行取负操作

  2. 结果存入目标寄存器(Sd)

  3. 实质操作:反转浮点数的符号位(符合IEEE 754标准)

技术特性

  • 支持单精度浮点运算(.F32后缀)

  • 符号位反转不影响数值位和指数位

状态标志

本指令不影响任何状态标志位

3.10.23 VNMLA(浮点负乘加), VNMLS(浮点负乘减), VNMUL(浮点负乘)

 

浮点融合乘加/乘减/乘取负指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Sd:目标寄存器(VNMUL可缺省)

  • Sn/Sm:乘数操作数寄存器

运算逻辑

VNMLA指令:

  1. 计算:-(Sn × Sm) + (-Sd)

  2. 结果回写至Sd

VNMLS指令:

  1. 计算:(Sn × Sm) + (-Sd)

  2. 结果回写至Sd

VNMUL指令:

  1. 计算:-(Sn × Sm)

  2. 结果存入Sd(缺省时替换Sn)

技术特性

  • 全系列支持单精度浮点(.F32)

  • 符合IEEE 754标准运算规则

  • VNMUL支持目标寄存器缺省模式

状态标志

本系列指令不影响任何状态标志位

3.10.24 VPOP(浮点出栈)

 

浮点扩展寄存器出栈指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • .size:可选数据位宽标识符:

    • 32:单精度(对应S寄存器)

    • 64:双精度(对应D寄存器)

  • list:寄存器列表(需用花括号包裹的连续编号寄存器,如{S0-S3})

操作特性

  1. 从堆栈内存连续加载多个浮点寄存器

  2. 自动递增堆栈指针(隐含回写)

  3. 支持单/双精度混合加载(需匹配.size声明)

使用限制

  1. 寄存器列表必须满足:

    • 至少包含1个寄存器

    • 最多16个双精度寄存器

  2. 数据位宽必须与寄存器类型匹配

状态标志

本指令不影响任何状态标志位

3.10.25 VPUSH(浮点压栈)

 

浮点扩展寄存器入栈指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • .size:可选数据位宽标识符:

    • 32:单精度(对应S寄存器)

    • 64:双精度(对应D寄存器)

  • list:寄存器列表(需用花括号包裹的连续编号寄存器,如{D0-D3})

操作特性

  1. 将多个连续浮点寄存器值压入堆栈

  2. 自动递减堆栈指针(隐含地址回写)

  3. 支持单/双精度混合存储(需匹配.size声明)

使用限制

  1. 寄存器列表必须满足:

    • 至少包含1个寄存器

    • 最多16个双精度寄存器

  2. 数据位宽必须与寄存器类型严格对应

状态标志

本指令执行不影响任何处理器状态标志

3.10.26 VSORT(浮点排序)

 

浮点平方根运算指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Sd:目标浮点寄存器(存储计算结果)

  • Sm:源浮点操作数寄存器

运算特性

  1. 计算源寄存器(Sm)中单精度浮点数的平方根

  2. 结果写入目标寄存器(Sd)

  3. 符合IEEE 754标准运算规则

技术规范

  • 支持单精度浮点运算(.F32后缀)

  • 自动处理非数值(NaN)和无穷大(Infinity)特殊情况

  • 支持条件执行

状态标志

本指令不影响任何状态标志位

3.10.27 VSTM(浮点多寄存器存储)

 

浮点多寄存器存储指令

语法

 

参数说明

  • mode 寻址模式:

    • IA(默认):从Rn地址开始顺序存储(可省略)

    • DB:在Rn地址前结束存储

  • cond:可选条件码(参见第65页条件执行章节)

  • .size:数据位宽标识符(32/64位,需与寄存器类型匹配)

  • Rn:基址寄存器(支持SP堆栈指针)

  • !:地址回写标志(DB模式必须启用)

  • list:寄存器列表(如{S0-S3}或{D1,D3})

操作特性

  1. 将多个连续浮点寄存器值存入连续内存地址

  2. 支持两种地址更新方式:

    • IA模式:先存储后递增地址

    • DB模式:先递减地址后存储

使用限制

  1. 寄存器列表要求:

    • 至少包含1个寄存器

    • 双精度寄存器最多16个

  2. 禁止使用PC作为基址寄存器

状态标志

本指令不影响任何状态标志位

3.10.28 VSTR(浮点单寄存器存储)

 

浮点单寄存器存储指令

语法

 

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • .32/.64:数据位宽标识符(需与寄存器类型匹配)

  • Sd/Dd:源浮点寄存器(单/双精度)

  • Rn:基址寄存器(支持SP堆栈指针)

  • imm:立即数偏移量(±1020范围内4的倍数,可缺省)

操作特性

  1. 将浮点寄存器值存储至内存地址:

    • 计算地址:[Rn + imm](imm缺省时为[Rn]

  2. 支持两种精度模式:

    • 单精度模式(.32):占用4字节内存

    • 双精度模式(.64):占用8字节内存

使用限制

  • 禁止使用PC作为基址寄存器

  • 地址必须按4字节对齐

状态标志

本指令不影响任何状态标志位

3.10.29 VSUB(浮点减法)

 

浮点减法指令

语法

参数说明

  • cond:可选条件码(参见第65页条件执行章节)

  • Sd:目标寄存器(可省略,默认为Sn)

  • Sn:被减数寄存器

  • Sm:减数寄存器

运算规则

  1. 执行单精度浮点减法运算:Sn - Sm

  2. 结果存入目标寄存器Sd

技术特性

  • 符合IEEE 754单精度浮点标准

  • 支持条件执行

  • 目标寄存器可选(缺省时替换首个操作数)

状态标志

本指令不影响任何状态标志位

3.11 杂项指令

 

表36展示了Cortex-M4架构中剩余的指令集:

 

助记符简要说明参见
BKPT 断点 第181页BKPT
CPSID 改变处理器状态,禁用中断 第182页CPS
CPSIE 改变处理器状态,启用中断 第182页CPS
DMB 数据内存屏障 第183页DMB
DSB 数据同步屏障 第184页DSB
ISB 指令同步屏障 第185页ISB
MRS 从特殊寄存器移动到寄存器 第186页MRS
MSR 从寄存器移动到特殊寄存器 第187页MSR
NOP 空操作 第188页NOP
SEV 发送事件 第189页SEV
SVC 管理程序调用 第190页SVC
WFE 等待事件 第191页WFE
WFI 等待中断 第192页WFI

3.11.1 BKPT(断点指令)

断点指令

语法

其中:

  • 'imm' 是一个表达式,其求值结果必须是 0-255 范围内的整数(8 位值)。

操作

BKPT 指令会使处理器进入调试状态。调试工具可以利用该指令在特定地址的指令被执行时检查系统状态。
处理器会忽略 imm 的值,但调试器可以将其用于存储与断点相关的附加信息。

BKPT 指令可以放置在 IT 指令块内,但其执行是无条件的,不受 IT 指令所指定条件的影响。

条件标志位

该指令不会改变标志位。

示例

BKPT 0xAB ; 断点指令,立即数值设为 0xAB(调试器可通过程序计数器 PC 定位该指令并提取立即数值)

3.11.2 CPS(修改处理器状态)

处理器状态切换指令

语法

其中:

  • effect 为以下选项之一:
    IE:清除特殊功能寄存器
    ID:设置特殊功能寄存器

  • iflags 为一个或多个标志位的组合:
    i:设置或清除 PRIMASK
    f:设置或清除 FAULTMASK

操作
CPS 指令用于修改 PRIMASK 和 FAULTMASK 特殊功能寄存器的值。有关这些寄存器的详细信息,请参阅第23页的"异常屏蔽寄存器"部分。

限制条件
使用该指令时需注意以下限制:

  • 仅可在特权级软件中使用,在非特权级软件中执行无效

  • 该指令不支持条件执行,因此不得在 IT 指令块中使用

条件标志位
该指令不会改变条件标志位。

示例

CPSID i ; 禁用中断及可配置的故障处理程序(设置 PRIMASK)
CPSID f ; 禁用中断及所有故障处理程序(设置 FAULTMASK)
CPSIE i ; 启用中断及可配置的故障处理程序(清除 PRIMASK)
CPSIE f ; 启用中断及所有故障处理程序(清除 FAULTMASK)

3.11.3 DMB(数据内存屏障)

数据内存屏障指令

语法

其中:

  • cond 为可选条件码(详见第65页"条件执行"说明)

操作
DMB 作为数据内存屏障:

  1. 确保在程序顺序中位于 DMB 之前的所有显式内存访问操作

  2. 必须优先于在程序顺序中位于 DMB 之后的所有显式内存访问操作完成

  3. 不影响非内存访问指令的执行顺序

条件标志位
该指令不会改变条件标志位。

示例

DMB ; 执行数据内存屏障操作

3.11.4 DSB(数据同步屏障)

数据同步屏障指令

语法

其中:

  • cond 为可选条件码(参见第65页"条件执行"章节)

操作
DSB 作为特殊的数据同步内存屏障:

  1. 确保程序顺序中位于 DSB 之后的所有指令

  2. 必须等待 DSB 指令执行完毕才能开始执行

  3. DSB 指令的完成条件:其之前的所有显式内存访问操作必须全部完成

条件标志位
该指令不会改变任何条件标志位。

示例

DSB ; 执行数据同步屏障操作

3.11.5 ISB(指令同步屏障)

指令同步屏障

语法

其中:

  • cond 为可选条件码(参见第65页"条件执行"章节)

操作
ISB 作为指令同步屏障:

  1. 清空处理器流水线

  2. 确保 ISB 之后的所有指令

  3. 在 ISB 指令完成后重新从缓存或内存中预取

条件标志位
该指令不会改变任何条件标志位。

示例

ISB ; 执行指令同步屏障操作

3.11.6 MRS(从系统寄存器读取到通用寄存器)

将特殊寄存器内容传送至通用寄存器

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Rd:目标寄存器

  • spec_reg:支持以下特殊寄存器:
    APSR、IPSR、EPSR、IEPSR、IAPSR、EAPSR、PSR
    MSP、PSP、PRIMASK、BASEPRI、BASEPRI_MAX、FAULTMASK、CONTROL

操作说明

  1. 该指令需与MSR指令配合使用,构成"读取-修改-写入"操作序列
    (典型应用场景:清除PSR中的Q标志位,详见第187页MSR指令说明)

  2. 在进程切换代码中:

    • 换出进程时:需保存包括PSR内容在内的程序模型状态(使用MRS指令)

    • 换入进程时:需恢复程序状态(使用MSR指令)

  3. 注:当与MRS指令配合使用时,BASEPRI_MAX是BASEPRI的别名

使用限制

  • 目标寄存器Rd不可为SP(堆栈指针)或PC(程序计数器)

条件标志位
该指令不影响任何条件标志位

应用示例

MRS R0, PRIMASK ; 读取PRIMASK寄存器值并存入R0

3.11.7 MSR(从通用寄存器写入系统寄存器)

将通用寄存器内容传送至特殊寄存器

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

  • Rn:源寄存器

  • spec_reg:支持以下特殊寄存器:
    APSR、IPSR、EPSR、IEPSR、IAPSR、EAPSR、PSR
    MSP、PSP、PRIMASK、BASEPRI、BASEPRI_MAX、FAULTMASK、CONTROL

操作说明

  1. 权限控制:

    • 非特权级软件仅能访问APSR(参见第21页表5:APSR位定义)

    • 特权级软件可访问所有特殊寄存器

  2. 写入规则:

    • 非特权级软件对PSR中未分配位或执行状态位的写入将被忽略

    • 向BASEPRI_MAX写入时,仅在以下情况会实际写入BASEPRI:

      • Rn 非零且当前BASEPRI值为0

      • Rn 非零且小于当前BASEPRI值
        (详见第186页MRS指令说明)

使用限制

  • 源寄存器Rn不可为SP(堆栈指针)或PC(程序计数器)

条件标志位

该指令会根据_Rn_的值显式更新条件标志位

应用示例

 

MSR CONTROL, R1 ; 读取R1寄存器值并写入CONTROL寄存器

3.11.8 NOP(空操作)

空操作指令

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

操作特性

  1. 本指令不执行任何实际操作

  2. 不保证消耗时钟周期(处理器可能在流水线执行阶段前将其移除)

典型应用

  • 代码对齐填充(如使后续指令按64位边界对齐)

条件标志位

该指令不影响任何条件标志位

应用示例

NOP ; 执行空操作

3.11.9 SEV(发送事件)

事件发送指令

语法


参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

操作特性

  1. 提示性指令(hint instruction)

  2. 在多处理器系统中向所有处理器发送事件信号

  3. 同时将本地事件寄存器置1(详见第47页"电源管理"章节)

条件标志位

该指令不影响任何条件标志位

应用示例

SEV ; 发送事件信号

3.11.10 SVC(超级用户调用)

管理程序调用指令

语法

参数说明:

  • cond:可选条件码(参见第65页条件执行章节)

  • imm:8位立即数(取值范围0-255)

操作特性

  1. 触发SVC异常

  2. 处理器忽略imm参数值

  3. 异常处理程序可通过检查该值确定请求的服务类型

条件标志位

该指令不影响任何条件标志位

应用示例

SVC 0x32 ; 管理程序调用(异常处理程序可通过堆栈中的PC值获取立即数)

3.11.11 WFE(等待事件)

事件等待指令(提示性指令)

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

操作逻辑

  1. 事件寄存器为0时:

    • 暂停执行直至以下任一事件发生:

      • 未被异常屏蔽寄存器或当前优先级屏蔽的异常

      • 当系统控制寄存器SEVONPEND位置1时,进入Pending状态的异常

      • 调试功能启用时的调试入口请求

      • 多处理器系统中外设或其他处理器通过SEV指令发出的事件信号

  2. 事件寄存器为1时:

    • 立即将寄存器清零并继续执行

(详见第47页"电源管理"章节)

条件标志位

该指令不影响任何条件标志位

应用示例

 

WFE ; 进入事件等待状态

3.11.12 WFI(等待中断)

中断等待指令

语法

参数说明:

  • cond:可选条件码(参见第65页"条件执行"章节)

操作特性

  1. 提示性指令(hint instruction)

  2. 暂停执行直至以下任一事件触发:

    • 任意外部中断/异常

    • 调试入口请求(无论调试功能是否启用)

条件标志位

该指令不影响任何条件标志位

应用示例

WFI ; 进入中断等待状态

 

posted @ 2025-06-10 07:20  明er  阅读(419)  评论(0)    收藏  举报