ARM 中的快速乘法指令文章目录ARM 中的快速乘法指令一、基本乘法指令32位结果1. MUL – 乘法32位2. MLA – 乘加32位二、长乘法指令64位结果1. UMULL – 无符号长乘法2. UMLAL – 无符号长乘加3. SMULL – 有符号长乘法4. SMLAL – 有符号长乘加三、DSP增强乘法指令ARMv5TE及以上1. SMLAxy – 带符号乘加并饱和2. SMLAWx – 带符号乘加32位×16位3. SMULxy – 带符号乘16位×16位4. SMLALxy – 带符号长乘加16位×16位累加到64位5. SMULWx – 带符号乘32位×16位→48位四、SIMD乘法指令ARMv6及以上1. SMLAD / SMLSD – 双16位乘加/乘减2. SMLALD / SMLSLD – 双16位乘加/乘减64位累加3. SMUAD / SMUSD – 双16位乘加/乘减无累加4. SMMLA / SMMLS / SMMUL – 32位乘高半字五、乘法指令的执行周期六、如何选择快速乘法指令七、编程示例八、总结ARM架构提供了丰富的乘法指令支持从基本的32位乘法到带累加的长乘法以及针对DSP数字信号处理优化的增强型乘法。这些指令在处理器实现中通常具有固定的执行周期如单周期或双周期因此被称为“快速乘法指令”。下面从指令分类、操作数格式、执行周期和适用场景等方面详细介绍。一、基本乘法指令32位结果1.MUL– 乘法32位语法MUL{cond} {S} Rd, Rm, Rs操作Rd Rm * Rs说明将两个32位寄存器相乘结果的低32位写入Rd。若结果超过32位高位被丢弃。条件码可选设置S标志影响N和Z位C和V未定义。周期在ARM7TDMI中为25周期取决于操作数中1的个数ARM9E及以后多为12周期。2.MLA– 乘加32位语法MLA{cond} {S} Rd, Rm, Rs, Rn操作Rd (Rm * Rs) Rn说明先乘法再加结果低32位存入Rd同样丢弃高位。周期与MUL类似但加法额外消耗少量周期部分处理器可并行处理。二、长乘法指令64位结果这类指令产生64位结果分为无符号和有符号两类适合需要高精度的运算如大数乘法、定点乘法累加。1.UMULL– 无符号长乘法语法UMULL{cond} {S} RdLo, RdHi, Rm, Rs操作[RdHi, RdLo] Rm * RsRdHi存放高32位RdLo存放低32位说明两个32位无符号数相乘得到64位无符号结果。2.UMLAL– 无符号长乘加语法UMLAL{cond} {S} RdLo, RdHi, Rm, Rs操作[RdHi, RdLo] (Rm * Rs) [RdHi, RdLo]说明累加之前已经存在于RdHi、RdLo中的64位值。3.SMULL– 有符号长乘法语法SMULL{cond} {S} RdLo, RdHi, Rm, Rs操作[RdHi, RdLo] Rm * Rs有符号乘法4.SMLAL– 有符号长乘加语法SMLAL{cond} {S} RdLo, RdHi, Rm, Rs操作[RdHi, RdLo] (Rm * Rs) [RdHi, RdLo]三、DSP增强乘法指令ARMv5TE及以上为了加速信号处理ARMv5TE引入了带饱和、双操作数等特殊乘法指令通常支持16位乘16位或32位乘16位的操作并累加到32位或64位累加器。1.SMLAxy– 带符号乘加并饱和语法SMLAxy Rd, Rm, Rs, Rn操作选择Rm和Rs中的半字16位相乘后与32位Rn相加结果写入Rd。若结果溢出则饱和到32位边界0x7FFFFFFF或0x80000000并设置Q标志。变种x和y可为B或T表示取高半字或低半字B 低半字T 高半字。如SMLABB取两个低半字SMLABT取Rm低半字、Rs高半字。常见指令SMLABB、SMLABT、SMLATB、SMLATT。2.SMLAWx– 带符号乘加32位×16位语法SMLAWx Rd, Rm, Rs, Rn操作将32位Rm与16位Rs半字相乘得到48位结果右移16位后与Rn相加写入Rd饱和。用途定点数运算例如将32位与16位系数相乘后累加。3.SMULxy– 带符号乘16位×16位语法SMULxy Rd, Rm, Rs操作两个16位半字相乘得到32位结果存入Rd。变种SMULBB、SMULBT、SMULTB、SMULTT。4.SMLALxy– 带符号长乘加16位×16位累加到64位语法SMLALxy RdLo, RdHi, Rm, Rs操作两个16位半字相乘结果符号扩展至64位加到[RdHi,RdLo]上。5.SMULWx– 带符号乘32位×16位→48位语法SMULWx Rd, Rm, Rs操作32位Rm与16位Rs半字相乘结果右移16位后存入Rd32位。常用于高精度乘法。四、SIMD乘法指令ARMv6及以上ARMv6开始引入单指令多数据SIMD乘法可同时处理多个16位或8位数据。1.SMLAD/SMLSD– 双16位乘加/乘减语法SMLAD Rd, Rm, Rs, Rn操作将Rm和Rs的16位半字两两相乘然后相加SMLAD或相减SMLSD结果加到Rn上存入Rd。2.SMLALD/SMLSLD– 双16位乘加/乘减64位累加语法SMLALD RdLo, RdHi, Rm, Rs操作类似SMLAD但累加到64位寄存器对。3.SMUAD/SMUSD– 双16位乘加/乘减无累加语法SMUAD Rd, Rm, Rs操作两个16位半字相乘后相加SMUAD或相减SMUSD结果存入32位Rd。4.SMMLA/SMMLS/SMMUL– 32位乘高半字语法SMMLA Rd, Rm, Rs, Rn操作32位Rm与Rs相乘取高32位结果再与Rn相加带可选的舍入控制。适合定点乘法。五、乘法指令的执行周期不同ARM内核的乘法指令周期差异较大但现代ARM处理器如Cortex-A系列、Cortex-M系列通常提供单周期或双周期的乘法。以下是一些典型数据内核乘法指令周期举例说明ARM7TDMIMUL: 25周期取决于操作数早期内核周期不固定ARM9E/ARM10E基本乘法12周期DSP乘法大多1周期优化了乘法器Cortex-M3/M4MUL1周期MLA1周期长乘35周期M4支持SIMD可并行计算Cortex-A8/A9大多数乘法2周期流水线后超标量可与其他指令并行Cortex-A53/A7612周期SIMD可并行高性能乘法通常单周期注意长乘法UMULL、SMULL等通常比基本乘法多12周期累加指令MLA、UMLAL等也可能因寄存器依赖而引入流水线停顿。六、如何选择快速乘法指令简单32位乘法使用MUL或MLA编译器通常自动选择。64位结果需要高精度时用UMULL/SMULL。DSP算法如FFT、滤波若数据为16位用SMLABB等半字指令可一次完成乘加节省指令数。若需并行处理两路16位数据使用SMLAD等SIMD指令。定点乘法用SMMLA系列取高32位避免移位操作。饱和运算使用带饱和的指令如SMLA自动处理溢出避免手动判断。七、编程示例; 基本32位乘法 MUL R0, R1, R2 ; R0 R1 * R2 ; 乘加并设置条件码 MLAS R0, R1, R2, R3 ; R0 R1*R2 R3, 更新N/Z ; 64位无符号乘法 UMULL R2, R3, R0, R1 ; [R3,R2] R0 * R1 ; 16位乘加DSP SMLABB R4, R5, R6, R7 ; R4 (R5低16位 * R6低16位) R7饱和 ; 双16位乘加SIMD SMLAD R8, R9, R10, R11 ; R8 (R9低*R10低 R9高*R10高) R11八、总结ARM的“快速乘法指令”涵盖了从基础到DSP优化的多种形式核心特点包括多种操作数宽度32位、16位、8位。支持累加和饱和减少额外指令。SIMD并行提高吞吐量。执行周期短多数现代内核中为12周期。在实际编程中应根据数据类型和算法需求选择合适的指令既可充分利用硬件加速又能保持代码简洁高效。若使用C语言现代编译器如ARM Compiler、GCC会自动将适当的乘法模式映射为对应的快速乘法指令需开启优化选项。