You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM NEON技术问询:如何对64位d寄存器执行整体位移位?

解决64位NEON d寄存器的寄存器指定逻辑移位问题

Hey, I get exactly what you're dealing with here—ARM NEON's vshl and vshr instructions operate per-element, meaning they only shift bits within each 64-bit element of the register, never crossing element boundaries to treat the entire d-register as a single 64-bit integer. That's obviously not what you need for a full-register logical shift where the count comes from another register.

Let's break down the best solutions depending on your architecture:

方案1:借助通用寄存器(最推荐,简单高效)

通用寄存器(AArch64的x寄存器、AArch32的r寄存器)天生就是为整数移位这类操作设计的,这是最直接高效的方案,步骤如下:

  1. 将NEON d寄存器的64位值转移到通用寄存器中
  2. 用通用寄存器的逻辑移位指令(左移lsl、右移lsr)完成操作,移位位数由另一个通用寄存器提供
  3. 将结果移回NEON d寄存器

AArch64 示例代码

; 假设:
; - d0 = 要移位的64位整数值
; - x1 = 移位位数(0 ≤ x1 < 64)
mov x0, d0           ; 将d0的64位值转存到通用寄存器x0
lsl x0, x0, x1       ; 逻辑左移x1位,左端补0(替换为`lsr x0, x0, x1`做右移,右端补0)
mov d0, x0           ; 把移位结果转回d0寄存器

AArch32 示例代码

AArch32通用寄存器是32位,需要拆分64位d寄存器到两个32位通用寄存器后再组合:

; 假设:
; - d0 = 要移位的64位整数值
; - r2 = 移位位数(0 ≤ r2 < 64)
vmov r0, r1, d0       ; 将d0拆分为低32位(r0)和高32位(r1)

; 处理64位逻辑左移(替换为对应逻辑右移逻辑即可)
mov r3, r2
cmp r3, #32
blt .L_shift_less_32

; 移位位数≥32的情况
sub r3, r3, #32
mov r0, r1, lsl r3
mov r1, #0
b .L_shift_done

.L_shift_less_32:
; 移位位数<32的情况
mov r0, r0, lsl r3
orr r0, r0, r1, lsr #(32 - r3)
mov r1, r1, lsl r3

.L_shift_done:
vmov d0, r0, r1       ; 把组合后的64位结果转回d0

方案2:纯NEON指令实现(仅当无法使用通用寄存器时)

如果因为特殊限制不能用通用寄存器,可以用NEON的向量操作和位指令模拟全寄存器移位,这种方法更复杂且性能更低,但可以实现需求:

  • 将64位d寄存器扩展为128位q寄存器,高位补0
  • 将移位位数拆分为字节移位量和剩余位移位量
  • 用字节提取指令vext处理字节对齐的移位
  • 结合位移位vshl/vshr和或运算处理跨元素的剩余位移位

AArch64 示例代码

; 假设:
; - d0 = 要移位的64位值
; - d1 = 存储移位位数的寄存器(低6位有效)
mov w1, v1.s[0]        ; 提取移位位数到通用寄存器w1(仅用于计算,可替换为NEON标量操作)
and w1, w1, #63        ; 确保位数在0-63之间

mov w2, w1, lsr #3     ; 计算字节移位量:shift_count // 8
mov w3, w1, & #7       ; 计算剩余位移位量:shift_count % 8

; 扩展d0到128位,高位补0
mov v0.2d[1], #0

; 字节级左移,补0
mov v1.16b, #0
vext v0.16b, v0.16b, v1.16b, w2

; 处理剩余位的跨元素移位
mov v2.16b, v0.16b
vshl v2.16b, v2.16b, v3.16b
vshr v0.16b, v0.16b, #(8 - w3)
orr v0.16b, v0.16b, v2.16b

; 取低64位作为结果
mov d0, v0.d[0]

关键要点

  • vshl/vshr不适用的核心原因是它们是按元素操作的指令——只会在寄存器的每个64段子内部移位,不会把整个64位寄存器当作单一整数处理
  • 通用寄存器中转的方案几乎是最优选择:代码简洁、性能更高、调试更简单

内容的提问来源于stack exchange,提问作者Florian S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:33:19