【发布时间】:2017-01-09 15:20:41
【问题描述】:
SHLD/SHRD 指令是实现多精度移位的汇编指令。
考虑以下问题:
uint64_t array[4] = {/*something*/};
left_shift(array, 172);
right_shift(array, 172);
实现 left_shift 和 right_shift 这两个函数的最有效方法是什么?这两个函数对四个 64 位无符号整数数组进行移位操作,就好像它是一个大的 256 位无符号整数一样?
最有效的方法是使用 SHLD/SHRD 指令,还是在现代架构上有更好的(如 SIMD 版本)指令?
【问题讨论】:
-
您正在为哪种架构编程?如果你在 x86 上,你可能有最高 SSE3 的指令 [编辑:正如@Ruslan 指出的,你可能在 32 位模式下支持 AVX/AVX2],或者在 x86_64 上最高 AVX2(除非你非常幸运并且能够大型英特尔协处理器上的 AVX512 程序)。如果您使用的是 ARM 并且支持 NEON,那么还有 SIMD 移位指令。
-
取决于“172”是否固定,或者只是示例值:因为 172 是 21.5 个字节,允许您先将内容移动 21 个字节,然后将 11 个目标字节向右移动 4 次(即 3x
shrd) 并用零清除其他 21 个字节。如果您的值已经在寄存器中,请检查此问题以获取许多资源:stackoverflow.com/q/25248766/4271923 -
@Dalton 您也可以在 32 位模式下使用 AVX2(不过,限制为 8 个
ymmN寄存器,与xmmN一样)。 -
@Dalton 是的,它们都是前几代的扩展。这包括添加的
ZMM16-ZMM31,仍然可以通过相应的YMM和XMM寄存器在下部访问。 -
@Dalton 不,所有这些都可用(例如
vcvtpd2ps,这是cvtpd2ps的明确VEX 编码版本,或新的vextractf128)。只是由于 VEX 被映射到另一条指令(在长模式下被删除)或未定义(导致#UD),一些操作码会引用更高的寄存器,如YMM8,这意味着一些不同的东西。
标签: c assembly x86-64 bit-shift arbitrary-precision