Autor: | Wojciech Muła |
---|---|
Dodany: | 28.04.2008 |
Dany jest blok 8 bajtów:
|a0 a1 a2 a3 a4 a5 a6 a7| bajt 0 |b0 b1 b2 b3 b4 b5 b6 b7| |c0 c1 c2 c3 c4 c5 c6 c7| . |d0 d1 d2 d3 d4 d5 d6 d7| . |e0 e1 e2 e3 e4 e5 e6 e7| . |f0 f1 f2 f3 f4 f5 f6 f7| |g0 g1 g2 g3 g4 g5 g6 g7| |h0 h1 h2 h3 h4 h5 h6 h7| bajt 7
Wynikiem transpozycji ma być:
|a0 b0 c0 d0 e0 f0 g0 h0| bajt 0 |a1 b1 c1 d1 e1 f1 g1 h1| |a2 b2 c2 d2 e2 f2 g2 h2| . |a3 b3 c3 d3 e3 f3 g3 h3| . |a4 b4 c4 d4 e4 f4 g4 h4| . |a5 b5 c5 d5 e5 f5 g5 h5| |a6 b6 c6 d6 e6 f6 g6 h6| |a7 b7 c7 d7 e7 f7 g7 h7| bajt 7
Dzięki rozkazom SSE można dość łatwo dokonać tego działania. Algorytm wymaga 8 iteracji (równocześnie transponowane są dwa bloki), w każdej wykonywane są następujące kroki:
powielany jest i-ty bajt (np. i=4) — PSHUFB:
|d0 d1 d2 d3 d4 d5 d6 d7| |d0 d1 d2 d3 d4 d5 d6 d7| |d0 d1 d2 d3 d4 d5 d6 d7| |d0 d1 d2 d3 d4 d5 d6 d7| |d0 d1 d2 d3 d4 d5 d6 d7| |d0 d1 d2 d3 d4 d5 d6 d7| |d0 d1 d2 d3 d4 d5 d6 d7| |d0 d1 d2 d3 d4 d5 d6 d7|
maskowane są kolejne bity — PAND:
|d0 0 0 0 0 0 0 0| | 0 d1 0 0 0 0 0 0| | 0 0 d2 0 0 0 0 0| | 0 0 0 d3 0 0 0 0| | 0 0 0 0 d4 0 0 0| | 0 0 0 0 0 d5 0 0| | 0 0 0 0 0 0 d6 0| | 0 0 0 0 0 0 0 d7|
powielanie bitów — PCMPEQB (właściwie powielenie negacji bitów):
|d0 d0 d0 d0 d0 d0 d0 d0| |d1 d1 d1 d1 d1 d1 d1 d1| |d2 d2 d2 d2 d2 d2 d2 d2| |d3 d3 d3 d3 d3 d3 d3 d3| |d4 d4 d4 d4 d4 d4 d4 d4| |d5 d5 d5 d5 d5 d5 d5 d5| |d6 d6 d6 d6 d6 d6 d6 d6| |d7 d7 d7 d7 d7 d7 d7 d7|
pozostawienie bitów na i-tej pozycji — PANDN:
| 0 0 0 0 d0 0 0 0| | 0 0 0 0 d1 0 0 0| | 0 0 0 0 d2 0 0 0| | 0 0 0 0 d3 0 0 0| | 0 0 0 0 d4 0 0 0| | 0 0 0 0 d5 0 0 0| | 0 0 0 0 d6 0 0 0| | 0 0 0 0 d7 0 0 0|
połączenie wyników z wynikami innych iteracji — POR
Szkic programu:
; pxor %xmm1, %xmm1 ; xmm1 := packed_byte(0x00) movdqa MASK1, %xmm2 ; MASK1 = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80} * 2 pxor %xmm7, %xmm7 ; xmm7 - wynik movdqa (%esi), %xmm3 ; załadowanie 16 bajtów 0: xor %eax, %eax movl $16, %ecx 1: movdqu %xmm3, %xmm0 pshufb PATTERN(%eax), %xmm0 ; (1) -- PATTERN[i] = packed_byte(i) pand %xmm2, %xmm0 ; (2) pcmpeqb %xmm1, %xmm0 ; (3) pandn MASK2(%eax), %xmm0 ; (4) -- MASK2[i] = packed_byte(1 << i) por %xmm0, %xmm7 ; (5) addl $16, %eax cmp $16*16, %eax jb 1b subl $1, %ecx jnz 0b