在现代英特尔CPU(核心i7,沙桥)上进行128位移位的最有效方法是什么。
类似的代码在我最内层的循环中:
u128 a[N];
void xor() {
for (int i = 0; i < N; ++i) {
a[i] = a[i] ^ (a[i] >> 1) ^ (a[i] >> 2);
}
}
a[N]
中的数据几乎是随机的。
答案 0 :(得分:11)
使用说明 Shift Double 。
所以SHLD
或SHRD
指令,因为SSE并非用于此目的。
有一种clasic方法,这里有32位和64位CPU模式下128位左移16位的测试用例。
通过这种方式,您可以执行无限大小的移位,最多可达32/64位。 Yoo可以移位立即数位或cl寄存器中的数字。第一个指令操作符也可以处理内存中的变量。
在32位x86 CPU模式下,128位左移16位:
mov eax, $04030201;
mov ebx, $08070605;
mov ecx, $0C0B0A09;
mov edx, $100F0E0D;
shld edx, ecx, 16
shld ecx, ebx, 16
shld ebx, eax, 16
shl eax, 16
在64位x86 CPU模式下,128位左移16位:
mov rax, $0807060504030201;
mov rdx, $100F0D0E0B0C0A09;
shld rdx, rax, 16
shl rax, 16
答案 1 :(得分:3)
在这种特殊情况下,您可以使用x86 SHR和RCR指令的组合:
; a0 - bits 0-31 of a[i]
; a1 - bits 32-63 of a[i]
; a2 - bits 64-95 of a[i]
; a3 - bits 96-127 of a[i]
mov eax, a0
mov ebx, a1
mov ecx, a2
mov ecx, a3
shr eax, 1
rcr ebx, 1
rcr ecx, 1
rcr edx, 1
; b0 - bits 0-31 of b[i] := a[i] >> 1
; b1 - bits 32-63 of b[i] := a[i] >> 1
; b2 - bits 64-95 of b[i] := a[i] >> 1
; b3 - bits 96-127 of b[i] := a[i] >> 1
mov b0, eax
mov b1, ebx
mov b2, ecx
mov b3, edx
shr eax, 1
rcr ebx, 1
rcr ecx, 1
rcr edx, 1
; c0 - bits 0-31 of c[i] := a[i] >> 2 = b[i] >> 1
; c1 - bits 32-63 of c[i] := a[i] >> 2 = b[i] >> 1
; c2 - bits 64-95 of c[i] := a[i] >> 2 = b[i] >> 1
; c3 - bits 96-127 of c[i] := a[i] >> 2 = b[i] >> 1
mov c0, eax
mov c1, ebx
mov c2, ecx
mov c3, edx
如果您的目标是x86-64,则简化为:
; a0 - bits 0-63 of a[i]
; a1 - bits 64-127 of a[i]
mov rax, a0
mov rbx, a1
shr rax, 1
rcr rbx, 1
; b0 - bits 0-63 of b[i] := a[i] >> 1
; b1 - bits 64-127 of b[i] := a[i] >> 1
mov b0, rax
mov b1, rbx
shr rax, 1
rcr rbx, 1
; c0 - bits 0-63 of c[i] := a[i] >> 2 = b[i] >> 1
; c1 - bits 64-127 of c[i] := a[i] >> 2 = b[i] >> 1
mov c0, rax
mov c1, rbx
更新:更正了64位版本中的拼写错误