Spis treści
SSE3
Streaming SIMD Extensions 3 (SSE3, oznaczany również przez firmę Intel jako Prescott New Instructions lub PNI) – zestaw instrukcji SIMD wykorzystywany w architekturze IA-32. Wcześniejsze zestawy SIMD stosowane na platformie x86, od najstarszej to: MMX, 3DNow! (używany tylko przez AMD), SSE i SSE2.
SSE3 wprowadza 13 nowych rozkazów w stosunku do swojego poprzednika SSE2, są to:
FISTTP– do konwersji liczb zmiennoprzecinkowych do całkowitychADDSUBPS,ADDSUBPD,MOVSLDUP,MOVSHDUP,MOVDDUP– do arytmetyki zespolonejLDDQU– do kodowania wideoHADDPS,HSUBPS,HADDPD,HSUBPD– do grafiki (SIMD FP/AOS)MONITOR,MWAIT– do synchronizacji wątków
Intel wprowadził SSE3 2 lutego 2004 roku wraz z procesorem Pentium 4 Prescott, natomiast firma AMD w procesorach Athlon 64 od wersji E.
Nowe rozkazy
[edytuj | edytuj kod]Nowe rozkazy:
- rozkazy wektorowe działające albo na wektorach liczb zmiennoprzecinkowych pojedynczej albo podwójnej precyzji (tj. wektory 4 × 32 bity lub 2 × 64 bity):
ADDSUBPSADDSUBPDHADDPS,HSUBPSHADDPD,HSUBPDMOVSLDUP,MOVSHDUPMOVDDUP
FISTTP– nowy rozkaz FPULDDQUMONITORiMWAIT
Przed wprowadzaniem SSE3 prawie wszystkie rozkazy arytmetyczne występujące w MMX, SSE, SSE2 działały, jak to określa Intel, „pionowo” (ang. vertical), tj. argumentami działań zawsze są elementy z dwóch wektorów. Natomiast w SSE3 pojawiły się rozkazy działające „poziomo” (ang. horizontal) — argumentami operacji arytmetycznych są elementy tego samego wektora; te instrukcje to: HADDPS, HADDPD, HSUBPS, HSUBPD.
FISTTP
[edytuj | edytuj kod]Rozkaz koprocesora arytmetycznego zamieniający liczbę zmiennoprzecinkową zapisaną w wierzchołku stosu na liczbę całkowitą ze znakiem; trybem zaokrąglania zawsze jest ucinanie (ang. chop), niezależnie od ustawień zapisanych w rejestrze kontrolnym FPU. Liczba całkowita może być 16-, 32- lub 64-bitowa, zależnie od argumentu.
Zgłaszany jest wyjątek w przypadku, gdy konwersja jest niemożliwa (wartość przekracza zakres liczby całkowitej, albo jest klasy plus/minus nieskończoność lub NaN).
Rozkaz FISTTP to uproszczona wersja istniejącej instrukcji FISTP, w której tryb zaokrąglania sterowany jest poprzez słowo kontrolne koprocesora – jego ewentualna zmiana jest kosztowna (trzeba wykonać kilka lub kilkanaście dodatkowych instrukcji: zachować bieżące ustawienia, włączyć inny tryb zaokrąglania, wykonać FISTP, przywrócić poprzedni tryb).
ADDSUBPS
[edytuj | edytuj kod]Rozkaz działa na dwóch wektorach liczb zmiennoprzecinkowych pojedynczej precyzji. Wykonywane jest dodawanie elementów o nieparzystych indeksach, odejmowanie – parzystych. Działania realizowane przez ADDSUBPS xmm1, xmm2:
xmm1[0] := xmm1[0] - xmm2[0] xmm1[1] := xmm1[1] + xmm2[1] xmm1[2] := xmm1[2] - xmm2[2] xmm1[3] := xmm1[3] + xmm2[3]
ADDSUBPD
[edytuj | edytuj kod]Rozkaz analogiczny do ADDSUBPS, działa na dwóch wektorach liczb zmiennoprzecinkowych podwójnej precyzji. Działania realizowane przez ADDSUBPD xmm1, xmm2:
xmm1[0] := xmm1[0] - xmm2[0] xmm1[1] := xmm1[1] + xmm2[1]
HADDPS, HSUBPS
[edytuj | edytuj kod]Rozkazy działają na wektorach liczb zmiennoprzecinkowych pojedynczej precyzji. HADDPS dodaje, zaś HSUBPS odejmuje sąsiednie elementy wektorów, tzn. HADDPS xmm1, xmm2 wykonuje:
temp[0] := xmm1[0] + xmm1[1] temp[1] := xmm1[2] + xmm1[3] temp[2] := xmm2[0] + xmm2[1] temp[3] := xmm2[2] + xmm2[3] xmm1 := temp
natomiast HSUBPS xmm1, xmm2:
temp[0] := xmm1[0] - xmm1[1] temp[1] := xmm1[2] - xmm1[3] temp[2] := xmm2[0] - xmm2[1] temp[3] := xmm2[2] - xmm2[3] xmm1 := temp
Np.:
3 2 1 0 3 2 1 0
+-----+-----+-----+-----+ +-----+-----+-----+-----+
| d | c | b | a | | h | g | f | e |
+-----+-----+-----+-----+ +-----+-----+-----+-----+
xmm1 xmm2
Wynik HADDPS:
+-----+-----+-----+-----+
xmm1 = | h+g | f+e | c+d | a+b |
+-----+-----+-----+-----+
Wynik HSUBPS:
+-----+-----+-----+-----+
xmm1 = | h-g | f-e | c-d | a-b |
+-----+-----+-----+-----+
HADDPD, HSUBPD
[edytuj | edytuj kod]Rozkazy działają na wektorach liczb zmiennoprzecinkowych podwójnej precyzji. Rozkaz HADDPD dodaje do siebie sąsiednie elementy wektorów, natomiast HSUBPD odejmuje. Instrukcja HADDPD xmm1, xmm2 wykonuje:
temp[0] := xmm1[0] + xmm1[1] temp[1] := xmm2[0] + xmm2[1] xmm1 := temp
natomiast HSUBPD xmm1, xmm2:
temp[0] := xmm1[0] - xmm1[1] temp[1] := xmm2[0] - xmm2[1] xmm1 := temp
MOVSLDUP, MOVSHDUP
[edytuj | edytuj kod]Rozkazy działają na wektorze liczb zmiennoprzecinkowych pojedynczej precyzji; rozkaz MOVSLDUP powiela elementy o parzystych indeksach, MOVHLDUP – o nieparzystych. Instrukcja MOVSLDUP xmm1, xmm2 wykonuje:
xmm1[0] := xmm2[0] xmm1[1] := xmm2[0] xmm1[2] := xmm2[2] xmm1[3] := xmm2[2]
natomiast MOVSHDUP xmm1, xmm2:
xmm1[0] := xmm2[1] xmm1[1] := xmm2[1] xmm1[2] := xmm2[3] xmm1[3] := xmm2[3]
Np.
3 2 1 0
+-----+-----+-----+-----+
xmm2 = | d | c | b | a |
+-----+-----+-----+-----+
Wynik MOVSLDUP:
+-----+-----+-----+-----+
xmm1 = | c | c | a | a |
+-----+-----+-----+-----+
Wynik MOVSHDUP:
+-----+-----+-----+-----+
xmm1 = | d | d | b | b |
+-----+-----+-----+-----+
MOVDDUP
[edytuj | edytuj kod]Argumentem rozkazu jest liczba zmiennoprzecinkowa podwójnej precyzji, która w rejestrze XMM jest powielana, tj. MOVDDUP xmm1, arg wykonuje:
xmm1[0] := arg xmm1[1] := arg
Argumentem może być albo lokacja pamięci (wówczas czytane są 64 bity), albo rejestr XMM, wówczas brane są jego 64 najmłodsze bity.
LDDQU
[edytuj | edytuj kod]Rozkaz ładuje 128 bitów spod adresów niewyrównanych do granicy 16 bajtów (tj. adresy mający niezerowe 4 najmłodsze bity). Rozkaz realizuje działanie analogiczne do istniejącego w SSE MOVDQU, jednak został specjalnie zoptymalizowany do kodu o następującej charakterystyce:
- występuje spadek wydajności spowodowany częstymi odczytami obszarów znajdujących się na granicy linijek cache,
- dane są tylko odczytywane i nie mają zostać (po ewentualnej modyfikacji) z powrotem zapisane pod tym samym adresem.
W przeciwnym razie producent poleca, by nadal używać rozkazów SSE MOVDQU lub MOVDQA.
MONITOR i MWAIT
[edytuj | edytuj kod]Para rozkazów służy do efektywnego synchronizowania wątków.
Rozkaz MONITOR ustala początkowy adres zakresu pamięci (rozmiar tego obszaru jest stały, zależny od modelu procesora), który następnie jest automatycznie monitorowany przez procesor: w przypadku wystąpienia zapisu gdziekolwiek w obserwowanym zakresie ustawiana jest wewnętrzna flaga, którą odczytuje MWAIT.
Wykonanie rozkazu MWAIT powoduje wejście w zoptymalizowaną sprzętową pętlę, która jest przerywana, dopiero gdy wspomniana flaga zostanie ustawiona, a więc gdy nastąpi zapis pod obserwowany adres.
Producenci procesorów mogą rozszerzać funkcjonalność tych rozkazów, dlatego m.in. możliwe jest przejście w tryb oszczędzanie energii na czas wykonywania MWAIT.
Bibliografia
[edytuj | edytuj kod]- Intel 64 and IA-32 Architectures Software Developer's Manual: Volume 2A: Instruction Set Reference, A-M (253666), maj 2007









