【问题标题】:Which architectures have modulo- / non-modulo-shifting?哪些架构具有模数/非模数移位?
【发布时间】:2021-12-18 10:30:03
【问题描述】:

当您在 x86 上使用可变移位计数(在 CL 中)移位一个值时,移位计数以目标操作数的位大小为模。但是是否存在没有这种模运算的架构,即如果我移动的距离超过操作数中的位,则操作数变为零(如果我移动无符号)?

【问题讨论】:

  • 较旧的 NVIDIA GPU 架构具有专用的左移和右移指令,可将移位计数限制为 0...32。较新的 NVIDIA GPU 架构提供了一个带有修饰符的统一漏斗移位指令,允许人们选择固定移位量(移位计数 0...32)或包装(移位计数 0...31),例如shf.l.clamp.b32shf.r.wrap.b32.

标签: assembly x86 x86-64 cpu-architecture bit-shift


【解决方案1】:

x86-64 标量移位对于 8 位和 16 位操作数大小是 mod-32。只有 32 和 64 位移位是以操作数大小为模的。 (8086 中根本不存在模数,因此能够移出 16 位寄存器中的所有位是perhaps a relevant backwards-compat issue for 186。但是对于像 386 和 amd64 这样的新扩展,没有兼容性问题,所以他们可以定义语义允许在没有额外条件的情况下使用更窄的桶形移位器。)

正如 Alex 所提到的,x86 SIMD 移位使移位计数饱和,当 >= 元素大小时移出所有位。例如,pslld xmm0, xmm1(是的,他们查看源的低元素的全宽,而不仅仅是低字节。)


ARM 使用所有位 in the low byte of the shift-count 寄存器进行可变计数移位。即modulo reduced to 0..255, then saturated to 0..32。 (有趣的事实:对于即时轮班,it is possible to encode LSR by 1..32, but only LSL by 0..31

IDK 其他 ISA 做什么;可能有一些类似于 x86 SIMD 转换。

【讨论】:

  • “低字节”行为适用于 ARM32。从手册中可以看出,ARM64 像 x86 一样切换到“mod 32 / 64”。不过还没有测试过。有点奇怪 - 世界上真的有人想要屏蔽行为吗?饱和不是只需要另外三个门吗? (如果设置了 6-63 位中的任何一个,则返回 0。)
  • @NateEldredge:我知道掩码的唯一优点是它可以轻松编写匹配任何输入的 asm 行为的无 UB C。例如x << (n&31) 可以优化为 shlx。与表达旋转相关,其中相反方向的偏移将超出范围而无需屏蔽,尽管在实际具有旋转的 ISA 上都可以优化掉。 Best practices for circular shift (rotate) operations in C++
  • 另外有趣的是,看起来 ARM64 的 SIMD 移位(USHL 和朋友)回到了 ARM32 行为,其中使用低字节并且大于字大小的移位产生零。除了一个真正饱和的表格USHLQ,如果你从左端移动一个 1 位(即“乘法”溢出),你会得到最大的无符号整数值(全为 1 位)。
【解决方案2】:

x86 也有非模移位,如果您考虑 MMX/SSE2/AVX2 psrlqpsllw

【讨论】:

    猜你喜欢
    • 2013-08-26
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    相关资源
    最近更新 更多