128-битные сдвиги с использованием языка ассемблера?

Каков наиболее эффективный способ сделать 128-битный сдвиг на современном процессоре Intel (ядро i7, песчаный мост).

Подобный код находится в моем самом внутреннем цикле:

u128 a[N];
void xor() {
  for (int i = 0; i < N; ++i) {
    a[i] = a[i] ^ (a[i] >> 1) ^ (a[i] >> 2);
  }
}

Данные в a[N] являются почти случайными.

6
задан Łukasz Lew 24 окт. '11 в 4:10
источник поделиться
2 ответов

Использование команды Сдвиг двойной.

So SHLD или SHRD, потому что SSE не предназначен для этой цели. Существует классический метод, вот у вас есть тестовые примеры для 128-битного сдвига влево на 16 бит в режиме 32 и 64-битного процессора.

Таким образом, вы можете выполнять неограниченный сдвиг по размеру до 32/64 бит. Yoo может сдвигаться для немедленного количества бит или числа в регистре cl. Оператор первой инструкции также может обращаться к переменной в памяти.

128 бит сдвиг влево на 16 бит при 32-битном режиме процессора x86:

    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

И 128 бит сдвиг влево на 16 бит в режиме 64-битного x86 CPU:

    mov    rax, $0807060504030201;
    mov    rdx, $100F0D0E0B0C0A09;

    shld   rdx, rax, 16
    shl    rax, 16
9
ответ дан GJ. 24 окт. '11 в 11:44
источник поделиться

В этом конкретном случае вы можете использовать комбинацию команд 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-разрядной версии

3
ответ дан Marat Dukhan 25 окт. '11 в 6:48
источник поделиться

Другие вопросы по меткам