R2026.05.1 - filtrowanie obrazu przy pomocy SSE
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
# Jan Potocki 2020
|
||||
|
||||
.globl filter
|
||||
.type filter, @function
|
||||
|
||||
.data
|
||||
# Pozwala uzyc rozkazu movdqa zamiast movdqu
|
||||
.align 16
|
||||
|
||||
# Macierz k w 4 kopiach - do rejestru xmm zmiescimy dane dla 4 pikseli splotu
|
||||
# 1. wiersz macierzy dopelniony do 32 bitow
|
||||
kernel128_1:
|
||||
.byte -1, -1, 0, 0
|
||||
.byte -1, -1, 0, 0
|
||||
.byte -1, -1, 0, 0
|
||||
.byte -1, -1, 0, 0
|
||||
# 2. wiersz macierzy dopelniony do 32 bitow
|
||||
kernel128_2:
|
||||
.byte -1, 0, 1, 0
|
||||
.byte -1, 0, 1, 0
|
||||
.byte -1, 0, 1, 0
|
||||
.byte -1, 0, 1, 0
|
||||
# 3. wiersz macierzy dopelniony do 32 bitow
|
||||
kernel128_3:
|
||||
.byte 0, 1, 1, 0
|
||||
.byte 0, 1, 1, 0
|
||||
.byte 0, 1, 1, 0
|
||||
.byte 0, 1, 1, 0
|
||||
|
||||
# Stala na potrzeby normalizacji - wartosc splotu z k miesci sie w przedziale
|
||||
# od 3*(-1*255) do 3*(1*255) czyli <-765,765>, wiec dodanie 765 pozwoli
|
||||
# przesunac ja w przedzial <0,1530>.
|
||||
# Na tym etapie obliczen liczby beda zapisane w 16-bitowej reprezentacji.
|
||||
bias128: .word 765, 765, 765, 765, 765, 765, 765, 765
|
||||
|
||||
# Argumenty:
|
||||
# rdi - adres M
|
||||
# rsi - adres W
|
||||
# rdx - rozdzielczosc w poziomie
|
||||
# rcx - rozdzielczosc w pionie
|
||||
|
||||
.text
|
||||
|
||||
filter:
|
||||
push %rbp
|
||||
mov %rsp, %rbp
|
||||
push %r15
|
||||
push %r14
|
||||
push %r13
|
||||
push %r12
|
||||
|
||||
# r15 - warunek stopu dla petli SIMD, tyle ile zmiesci sie w wierszu
|
||||
mov %rdx, %r15
|
||||
sub $17, %r15
|
||||
# r14 - warunek stopu dla petli indeksujacej wiersze
|
||||
mov %rcx, %r14
|
||||
sub $2, %r14
|
||||
# r12 - warunek stopu dla petli pomocniczej, dokonczenie wiersza
|
||||
mov %rdx, %r12
|
||||
sub $2, %r12
|
||||
# ...w tej implementacji skrajne piksele obrazu wynikowego pomijamy
|
||||
|
||||
# Wpisanie stalych do rejestrow aby przyspieszyc obliczenia
|
||||
movdqa bias128, %xmm12
|
||||
movdqa kernel128_1, %xmm13
|
||||
movdqa kernel128_2, %xmm14
|
||||
movdqa kernel128_3, %xmm15
|
||||
|
||||
# r9 - pomocniczy indeks adresujacy wiersze w pamieci
|
||||
xor %r9, %r9
|
||||
# r10 - indeks rozdzielczosci pionowej (wierszy)
|
||||
xor %r10, %r10
|
||||
|
||||
# Petla indeksujaca wiersze
|
||||
lp1:
|
||||
# r11 - indeks rozdzielczosci poziomej (pikseli w wierszu)
|
||||
xor %r11, %r11
|
||||
|
||||
# Podstawowa petla SIMD (16 pikseli na iteracje)
|
||||
lp2:
|
||||
# r8 - adres pikseli w pamieci (suma adresu wiersza i indeksu pikseli)
|
||||
mov %r9, %r8
|
||||
add %r11, %r8
|
||||
|
||||
# Instrukcja pinsrd kopiuje 4 kolejne 8-bitowe piksele do fragmentu xmm,
|
||||
# czyli tyle ile trzeba aby obliczyc splot z jednym wierszem k. Ostatni piksel
|
||||
# zachodzi na pierwszy kolejnego splotu - to nie ma znaczenia, bo kazdy wiersz
|
||||
# macierzy k jest do 32-bitowej postaci dopelniony zerem na ostatnim bajcie.
|
||||
# Instrukcja pmaddubsw oblicza iloczyn 8-bitowych pikseli obrazu i wartosci
|
||||
# kernela, sumuje dwa sasiednie iloczyny i w ich miejsce zapisuje wynik
|
||||
# w 16-bitowej reprezentacji U2.
|
||||
|
||||
# Gorny wiersz macierzy k
|
||||
pinsrd $0, 0(%rdi, %r8, 1), %xmm0
|
||||
pinsrd $1, 1(%rdi, %r8, 1), %xmm0
|
||||
pinsrd $2, 2(%rdi, %r8, 1), %xmm0
|
||||
pinsrd $3, 3(%rdi, %r8, 1), %xmm0
|
||||
pmaddubsw %xmm13, %xmm0
|
||||
|
||||
pinsrd $0, 4(%rdi, %r8, 1), %xmm1
|
||||
pinsrd $1, 5(%rdi, %r8, 1), %xmm1
|
||||
pinsrd $2, 6(%rdi, %r8, 1), %xmm1
|
||||
pinsrd $3, 7(%rdi, %r8, 1), %xmm1
|
||||
pmaddubsw %xmm13, %xmm1
|
||||
|
||||
pinsrd $0, 8(%rdi, %r8, 1), %xmm6
|
||||
pinsrd $1, 9(%rdi, %r8, 1), %xmm6
|
||||
pinsrd $2, 10(%rdi, %r8, 1), %xmm6
|
||||
pinsrd $3, 11(%rdi, %r8, 1), %xmm6
|
||||
pmaddubsw %xmm13, %xmm6
|
||||
|
||||
pinsrd $0, 12(%rdi, %r8, 1), %xmm7
|
||||
pinsrd $1, 13(%rdi, %r8, 1), %xmm7
|
||||
pinsrd $2, 14(%rdi, %r8, 1), %xmm7
|
||||
pinsrd $3, 15(%rdi, %r8, 1), %xmm7
|
||||
pmaddubsw %xmm13, %xmm7
|
||||
|
||||
add %rdx, %r8
|
||||
# Przechowanie adresu srodkowego wiersza na pozniej, do zapisu wyniku splotu
|
||||
mov %r8, %r13
|
||||
|
||||
# Srodkowy wiersz macierzy k
|
||||
pinsrd $0, 0(%rdi, %r8, 1), %xmm2
|
||||
pinsrd $1, 1(%rdi, %r8, 1), %xmm2
|
||||
pinsrd $2, 2(%rdi, %r8, 1), %xmm2
|
||||
pinsrd $3, 3(%rdi, %r8, 1), %xmm2
|
||||
pmaddubsw %xmm14, %xmm2
|
||||
|
||||
pinsrd $0, 4(%rdi, %r8, 1), %xmm3
|
||||
pinsrd $1, 5(%rdi, %r8, 1), %xmm3
|
||||
pinsrd $2, 6(%rdi, %r8, 1), %xmm3
|
||||
pinsrd $3, 7(%rdi, %r8, 1), %xmm3
|
||||
pmaddubsw %xmm14, %xmm3
|
||||
|
||||
pinsrd $0, 8(%rdi, %r8, 1), %xmm8
|
||||
pinsrd $1, 9(%rdi, %r8, 1), %xmm8
|
||||
pinsrd $2, 10(%rdi, %r8, 1), %xmm8
|
||||
pinsrd $3, 11(%rdi, %r8, 1), %xmm8
|
||||
pmaddubsw %xmm14, %xmm8
|
||||
|
||||
pinsrd $0, 12(%rdi, %r8, 1), %xmm9
|
||||
pinsrd $1, 13(%rdi, %r8, 1), %xmm9
|
||||
pinsrd $2, 14(%rdi, %r8, 1), %xmm9
|
||||
pinsrd $3, 15(%rdi, %r8, 1), %xmm9
|
||||
pmaddubsw %xmm14, %xmm9
|
||||
|
||||
add %rdx, %r8
|
||||
|
||||
# Dolny wiersz macierzy k
|
||||
pinsrd $0, 0(%rdi, %r8, 1), %xmm4
|
||||
pinsrd $1, 1(%rdi, %r8, 1), %xmm4
|
||||
pinsrd $2, 2(%rdi, %r8, 1), %xmm4
|
||||
pinsrd $3, 3(%rdi, %r8, 1), %xmm4
|
||||
pmaddubsw %xmm15, %xmm4
|
||||
|
||||
pinsrd $0, 4(%rdi, %r8, 1), %xmm5
|
||||
pinsrd $1, 5(%rdi, %r8, 1), %xmm5
|
||||
pinsrd $2, 6(%rdi, %r8, 1), %xmm5
|
||||
pinsrd $3, 7(%rdi, %r8, 1), %xmm5
|
||||
pmaddubsw %xmm15, %xmm5
|
||||
|
||||
pinsrd $0, 8(%rdi, %r8, 1), %xmm10
|
||||
pinsrd $1, 9(%rdi, %r8, 1), %xmm10
|
||||
pinsrd $2, 10(%rdi, %r8, 1), %xmm10
|
||||
pinsrd $3, 11(%rdi, %r8, 1), %xmm10
|
||||
pmaddubsw %xmm15, %xmm10
|
||||
|
||||
pinsrd $0, 12(%rdi, %r8, 1), %xmm11
|
||||
pinsrd $1, 13(%rdi, %r8, 1), %xmm11
|
||||
pinsrd $2, 14(%rdi, %r8, 1), %xmm11
|
||||
pinsrd $3, 15(%rdi, %r8, 1), %xmm11
|
||||
pmaddubsw %xmm15, %xmm11
|
||||
|
||||
# Suma kolumn splotu
|
||||
paddw %xmm2, %xmm0
|
||||
paddw %xmm3, %xmm1
|
||||
paddw %xmm8, %xmm6
|
||||
paddw %xmm9, %xmm7
|
||||
paddw %xmm4, %xmm0
|
||||
paddw %xmm5, %xmm1
|
||||
paddw %xmm10, %xmm6
|
||||
paddw %xmm11, %xmm7
|
||||
|
||||
# Suma wierszy splotu
|
||||
phaddw %xmm1, %xmm0
|
||||
phaddw %xmm7, %xmm6
|
||||
|
||||
# Normalizacja wyniku splotu - dodanie zdefiniowanego obciazenia i skalowanie
|
||||
# z powrotem do 8-bitowej reprezentacji.
|
||||
# Dokladny wynik pozwoliloby uzyskac dzielenie przez 6 (1530/6=255),
|
||||
# przesuniecie o 3 bity w prawo jest wydajniejsze, a wciaz pozwala uzyskac
|
||||
# rozsadna dokladnosc (1530>>3=191)
|
||||
paddw %xmm12, %xmm0
|
||||
paddw %xmm12, %xmm6
|
||||
psrlw $3, %xmm0
|
||||
psrlw $3, %xmm6
|
||||
|
||||
# Spakowanie 8-bitowych wynikow do jednego rejestru i zapis do pamieci
|
||||
packuswb %xmm6, %xmm0
|
||||
movdqu %xmm0, 1(%rsi, %r13, 1)
|
||||
|
||||
# Sprawdzenie, czy nastepna iteracja petli SIMD zmiesci sie w wierszu
|
||||
add $16, %r11
|
||||
cmp %r15, %r11
|
||||
jl lp2
|
||||
|
||||
# Sprawdzenie, czy wiersz zostal przeliczony w calosci...
|
||||
cmp %r12, %r11
|
||||
je next_row
|
||||
|
||||
# ...jesli nie - na dobieg pomocnicza petla (1 piksel na iteracje)
|
||||
lp2a:
|
||||
mov %r9, %r8
|
||||
add %r11, %r8
|
||||
|
||||
# Gorny wiersz macierzy k
|
||||
pinsrd $0, 0(%rdi, %r8, 1), %xmm0
|
||||
pmaddubsw %xmm13, %xmm0
|
||||
add %rdx, %r8
|
||||
mov %r8, %r13
|
||||
|
||||
# Srodkowy wiersz macierzy k
|
||||
pinsrd $0, 0(%rdi, %r8, 1), %xmm2
|
||||
pmaddubsw %xmm14, %xmm2
|
||||
add %rdx, %r8
|
||||
|
||||
# Dolny wiersz macierzy k
|
||||
pinsrd $0, 0(%rdi, %r8, 1), %xmm4
|
||||
pmaddubsw %xmm15, %xmm4
|
||||
|
||||
# Suma i normalizacja splotu
|
||||
paddw %xmm2, %xmm0
|
||||
paddw %xmm4, %xmm0
|
||||
phaddw %xmm0, %xmm0
|
||||
paddw %xmm12, %xmm0
|
||||
psrlw $3, %xmm0
|
||||
|
||||
# Spakowanie 8-bitowego wyniku w najmlodszym fragmencie rejestru i zapis
|
||||
packuswb %xmm0, %xmm0
|
||||
pextrb $0, %xmm0, 1(%rsi, %r13, 1)
|
||||
|
||||
# Sprawdzenie, czy tym razem wiersz jest juz przeliczony w calosci
|
||||
inc %r11
|
||||
cmp %r12, %r11
|
||||
jl lp2a
|
||||
|
||||
next_row:
|
||||
# Przesuniecie adresu wiersza w dol
|
||||
add %rdx, %r9
|
||||
# Sprawdzenie, czy caly obraz jest przeliczony
|
||||
inc %r10
|
||||
cmp %r14, %r10
|
||||
jl lp1
|
||||
|
||||
pop %r12
|
||||
pop %r13
|
||||
pop %r14
|
||||
pop %r15
|
||||
pop %rbp
|
||||
ret
|
||||
Reference in New Issue
Block a user