MMX (zestaw instrukcji)

MMX ( lub ) – zestaw 57 instrukcji SIMD dla procesorów Pentium i zgodnych. Rozkazy MMX mogą realizować działania logiczne i arytmetyczne na liczbach całkowitych. Pierwotnie wprowadzone w 1996 przez Intela dla procesorów Pentium MMX, dostępne również na procesory innych producentów. Wraz z rozwojem procesorów i dodawaniem nowych rozszerzeń (np. SSE) zbiór rozkazów MMX powiększał się. Instrukcje te są wykorzystywane przez procesory Intel Pentium MMX oraz AMD K6 i ich następców.

Programy wykorzystujące rozkazy MMX były o wiele szybsze od analogicznych programów wykorzystujących zwykłe rozkazy procesora. Jednak należy mieć na uwadze, iż MMX jest przeznaczony do szczególnych zastosowań, gdzie przetwarzane są duże ilości danych przez jeden określony algorytm – a więc na ogół będzie to obróbka dźwięku i obrazu. W zwykłych programach komputerowych korzyść z zastosowania MMX jest praktycznie żadna, wyparły je więc kolejne generacje rozkazów wektorowych SSE, SSE2 itd.

Przykłady zastosowań:
 wyświetlanie grafiki trójwymiarowej: przekształcenia geometryczne, cieniowanie, teksturowanie;
 dekodowanie obrazów JPEG i PNG;
 dekodowanie i kodowanie filmów MPEG (m.in. wyznaczanie transformat DCT i IDCT);
 filtrowanie sygnałów: obrazów statycznych, filmów, dźwięku;
 wyświetlanie grafiki dwuwymiarowej (blue box, maskowanie, przezroczystość);
 wyznaczanie transformat: Haara, FFT.

Rejestry 
Rejestry MMX mają rozmiar 64 bitów, jest ich 8. Miejsce jakie zajmują w architekturze procesora jest nietypowe – nie są bowiem niezależnymi komórkami pamięci, lecz są zamapowane na 64 młodsze bity rejestrów koprocesora arytmetycznego, normalnie przeznaczone na mantysę liczby zmiennoprzecinkowej. Każde odwołanie do rejestru MMX, zarówno odczyt, jak i zapis wartości, powoduje unieważnienie zawartości wszystkich rejestrów koprocesora. Ponieważ zdecydowano się na takie rozwiązanie, „wymieszanie” obliczeń MMX ze zmiennoprzecinkowymi jest niemożliwe. Z drugiej strony tę niedogodność rekompensuje fakt, że na procesorach Pentium MMX mogły działać bez przeszkód już istniejące programy (w szczególności systemy operacyjne).

Typy danych 
MMX wprowadził nowe typy danych, w języku angielskim nazwane packed, czyli dosłownie spakowane, upakowane; w języku polskim lepszym terminem oddającym ich charakter jest wektor i macierz lub tablica. Owo „spakowanie” polega na traktowaniu danych 64-bitowych jako składających się z pewnej liczby odrębnych komórek o tej samej wielkości:
 8 × 8 bitów (packed byte),
 4 × 16 bitów (packed word),
 2 × 32 bity (packed dword),
 1 × 64 bity (quad word).

Gdy wykonywane są działania na typach wektorowych („spakowanych”), ta sama operacja wykonywana jest dla wszystkich komórek jednocześnie. Np. jeśli dodawane są dwa wektory 8 × 8 bitów, to pojedynczy rozkaz wykonuje osiem operacji dodawania danych 8-bitowych i zapisywane jest osiem wyników 8-bitowych.

W przypadku niektórych rozkazów istotne jest rozróżnienie, czy operuje się na liczbach całkowitych bez znaku (ang. unsigned) czy ze znakiem (ang. signed).

Operacje logiczne i arytmetyczne

Arytmetyka 
MMX rozróżnia dwa rodzaje arytmetyki, w których różnie reaguje się na przekroczenie zakresu liczb:
 Arytmetyka nasyceniowa – jeśli wynik przekracza zakres jaki może pomieścić dany typ danych, to zapisywana jest wartość skrajna. Np. bajt bez znaku może przechowywać liczby z zakresu od 0 do 255 i jeśli do bajta o wartości 230 zostanie dodane 100, to wynikiem będzie 255, ponieważ 330 przekracza dopuszczalny zakres.
 Arytmetyka modulo (ang. wraparound), w której przekroczenie zakresu nie jest w żaden sposób sygnalizowane – zapisywane są tylko najmłodsze bity, które mieszczą się w słowie wynikowym. Dla danych z wcześniejszego przykładu wynikiem będzie 74, ponieważ z liczby  zostanie zapisane tylko 8 najmłodszych bitów, tj.

Porównania 
Ponieważ w MMX jednocześnie porównywane jest wiele elementów, nie są ustawiane żadne flagi ALU. Wynikiem porównania wektorów jest nowy wektor, w którym wartości poszczególnych elementów odpowiadają rezultatowi porównania: jeśli jest prawdziwy, wszystkie bity są ustawiane, gdy fałszywy – zerowane.

Przykład porównania ze względu na równość dwóch wektorów bajtów rozkazem PCMPEQB MM1, MM2:
       +--------+--------+--------+--------+--------+--------+--------+--------+
 MM1 = |01001000|01001100|10000100|00101110|11000100|01001110|11100000|00000001|
       +--------+--------+--------+--------+--------+--------+--------+--------+
       +--------+--------+--------+--------+--------+--------+--------+--------+
 MM2 = |00001000|01001100|10000100|10101111|11000100|01000000|11110111|00000001|
       +--------+--------+--------+--------+--------+--------+--------+--------+
           =        =        =        =        =        =        =        =
       +--------+--------+--------+--------+--------+--------+--------+--------+
 MM2 = |00000000|11111111|11111111|00000000|11111111|00000000|00000000|11111111|
       +--------+--------+--------+--------+--------+--------+--------+--------+

Rozkazy MMX 
 transferowe (przemieszczania danych) (2):
 (MOVD, MOVQ)
 arytmetyczne (17):
 dodawanie (PADDB, PADDW, PADDD)
 dodawanie z nasyceniem (PADDSB, PADDSW, PADDUSB, PADDUSW)
 odejmowanie (PSUBB, PSUBW, PSUBD)
 odejmowanie z nasyceniem (PSUBSB, PSUBSW, PSUBUSB, PSUBUSW)
 mnożenie (PMULHW, PMULLW)
 mnożenie z dodawaniem, tj. operacja  (PMADDWD)
 porównania (6):
 czy równe (PCMPEQB, PCMPEQW, PCMPEQD)
 czy większe (PCMPGTB, PCMPGTW, PCMPGTD)
 pakowania i rozpakowania wektorów (9):
 pakowania (PACKUSWB, PACKSSWB, PACKSSDW);
 rozpakowania mniej znaczących bajtów (PUNPCKLBW, PUNPCKLWD, PUNPCKLDQ)
 rozpakowania bardziej znaczących bajtów (PUNPCKHBW, PUNPCKHWD, PUNPCKHDQ)
 operacje logiczne (4):
 suma (POR)
 iloczyn (PAND)
 iloczyn z zanegowanym pierwszym z argumentów (PANDN)
 różnica symetryczna (PXOR)
 przesunięcia bitowe (8):
 w lewo (PSLLW, PSLLD, PSLLQ)
 w prawo (PSRLW, PSRLD, PSRLQ)
 arytmetyczne w prawo (PSRAW, PSRAD)
 specjalne (1):
 przygotowanie koprocesora do działań zmiennoprzecinkowych (EMMS).

Asembler 
Rejestry MMX w asemblerze noszą nazwy MM0, MM1–MM7.

Mnemoniki prawie wszystkich rozkazów MMX rozpoczynają się od litery P (od słowa packed); kolejne części (niektóre opcjonalne) nazwy mają następujące znaczenie:
 3–5 literowy skrót działania jakie dany rozkaz wykonuje (np. ADD, PACK, UNPCK);
 litera S lub U określająca, czy działanie wykonywane jest – odpowiednio – na liczbach ze znakiem (signed) lub bez znaku (unsigned);
 litera S jeśli operacja jest wykonywana z nasyceniem;
 litera L, H – dla odpowiednio mniej lub bardziej znaczących bajtów komórki wektora (tylko dla rozkazów: PUNPCKLBW, PUNPCKLWD, PUNPCKLDQ, PUNPCKHBW, PUNPCKHWD, PUNPCKHDQ).
 rozmiar komórki wektora: B – bajt (8 bitów), W – słowo (16 bitów), D – podwójne słowo (32 bity), Q – poczwórne słowo (64 bity).

Na przykład rozkaz PADDUSB wykonuje równoległe (P) dodawanie (ADD) bez znaku (U) z nasyceniem (S) bajtów (B).

Zobacz też 
 mikroprocesory firmy Intel
 kod stałopozycyjny
 3DNow!
 SSE, SSE2, SSE3, SSSE3, SSE4, SSE5, AVX

Przypisy 

Zestawy instrukcji procesora x86