Co znaczy „rep; nie; ” oznacza w montażu x86? Czy to to samo, co instrukcja „pauza”?

86
  • Co to rep; nopznaczy?
  • Czy to to samo, co pauseinstrukcja?
  • Czy to to samo co rep nop(bez średnika)?
  • Jaka jest różnica w stosunku do prostej nopinstrukcji?
  • Czy zachowuje się inaczej na procesorach AMD i Intel?
  • (bonus) Gdzie jest oficjalna dokumentacja tych instrukcji?

Motywacja do tego pytania

Po krótkiej dyskusji w komentarzach do innego pytania zdałem sobie sprawę, że nie wiem, co to rep; nop;znaczy w asemblerze x86 (lub x86-64). Nie mogłem też znaleźć dobrego wyjaśnienia w internecie.

Wiem, że repjest to przedrostek, który oznacza „powtórz czas następnej instrukcji cx (a przynajmniej tak było w starym 16-bitowym zestawie x86). Według tej tabeli podsumowującej w Wikipedii , wydaje się repmoże być używany tylko z movs, stos, cmps, lods, scas(ale może to ograniczenie zostało usunięte w nowszych procesorów). Dlatego myślę, że rep nop(bez średnika) powtórzyłbym nopoperację cxrazy.

Jednak po dalszych poszukiwaniach jeszcze bardziej się zdezorientowałem. Wydaje się, że rep; nopi pause map do dokładnie tego samego kodu operacji i pausema nieco inne zachowanie niż tylko nop. Niektóre stare listy z 2005 roku mówiły różne rzeczy:

  • „staraj się nie spalać zbyt dużo energii”
  • „jest to odpowiednik 'nop' tylko z kodowaniem 2-bajtowym”.
  • „To jest magia na temat danych wywiadowczych. To jak 'nie, ale niech ucieknie inne rodzeństwo HT'”
  • „jest przerwa w informacjach i szybkie uzupełnianie informacji na temat Athlona”

Przy tych różnych opiniach nie mogłem zrozumieć właściwego znaczenia.

Jest używany w jądrze Linuksa (zarówno na i386, jak i x86_64 ), wraz z następującym komentarzem: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */Jest również używany w BeRTOS , z tym samym komentarzem.

Denilson Sá Maia
źródło

Odpowiedzi:

75

rep; nopjest rzeczywiście taka sama jak pauseinstrukcja (kod operacji F390). Może być używany dla asemblerów, którzy jeszcze nie obsługują tej pauseinstrukcji. Na poprzednich procesorach to po prostu nic nie dało, tak jak noptylko w dwóch bajtach. W przypadku nowych procesorów obsługujących wielowątkowość jest używany jako wskazówka dla procesora, że ​​wykonujesz pętlę spinloop w celu zwiększenia wydajności. Z instrukcji firmy Intel :

Poprawia wydajność pętli spin-wait. Podczas wykonywania „pętli spin-wait” procesor Pentium 4 lub Intel Xeon doznaje poważnego spadku wydajności przy wychodzeniu z pętli, ponieważ wykrywa możliwe naruszenie kolejności pamięci. Instrukcja PAUSE stanowi wskazówkę dla procesora, że ​​sekwencja kodu jest pętlą spin-wait. Procesor wykorzystuje tę wskazówkę, aby uniknąć naruszenia kolejności pamięci w większości sytuacji, co znacznie poprawia wydajność procesora. Z tego powodu zaleca się umieszczenie instrukcji PAUSE we wszystkich pętlach spin-wait.

ughoavgfhw
źródło
4
Czy pętla spin-wait to to samo co pętla busy-wait ? Czy to „ulepszenie” dotyczy tylko procesorów wielowątkowości? (i dlaczego?)
Denilson Sá Maia
11
Tak, pętla spin-wait jest tym samym, co pętla busy-wait. Korzyść dotyczy również procesorów, które nie obsługują hiperwątkowości. Można to traktować jako ograniczenie liczby (niepotrzebnych) instrukcji w potoku (zamiast próby wykonywania wielu iteracji pętli równolegle)
Brendan,
1
@Brendan, dzięki! W ogóle nie rozumiałem, dopóki nie powiedziałeś rzeczy o równoległych iteracjach pętli.
Prof. Falken,
11
@Brendan, Oh, teraz rozumiem! Te nowoczesne procesory są superskalarne , więc będą próbowały wykonywać wiele instrukcji jednocześnie. Jeśli jest to pętla zajętego oczekiwania, wykonanie większej liczby instrukcji nie przyspieszy jej, ponieważ czeka na inny warunek.
Denilson Sá Maia
1
@Denilson: Tak, przyjazność dla wielowątkowości (lub po prostu oszczędzanie energii bez HT) to jedna duża korzyść, ale drugą jest uniknięcie błędnych spekulacji związanych z porządkowaniem pamięci podczas opuszczania pętli spinowej. Bez pausetego pętla spinowa jest efektywnie usuwana o jeden potok wolniej, aby zauważyć zmianę stanu lokalizacji pamięci zapisanej przez inny rdzeń.
Peter Cordes
14

rep nop= F3 90 = kodowanie pause, a także sposób dekodowania na starszych procesorach, które nie obsługują pause.


Prefiksy (inne niż lock), które nie dotyczą instrukcji, są w praktyce ignorowane przez istniejące procesory.

Dokumentacja mówi, że używanie repz instrukcjami, których nie dotyczy, jest „zastrzeżone i może powodować nieprzewidywalne zachowanie”, ponieważ przyszłe procesory mogą je rozpoznać jako część nowej instrukcji. Kiedy już ustalą nowe kodowanie instrukcji f3 xx, dokumentują, jak działa na starszych procesorach. (Tak, przestrzeń kodu operacji x86 jest tak ograniczona, że ​​robią takie szalone rzeczy i tak, to komplikuje dekodery).

W tym przypadku oznacza topause , że możesz używać w spinloopach bez przerywania wstecznej kompatybilności . Stare procesory, które nie wiedzą o pausetym, dekodują go jako NOP bez szkody, co jest gwarantowane przez ręczny wpis dotyczącypause ISA firmy Intel dla . W przypadku nowych procesorów zyskujesz oszczędność energii / przyjazność dla HT i unikasz błędnych spekulacji związanych z kolejnością pamięci, gdy pamięć, na której się obracasz, zmienia się i opuszczasz pętlę spinową.


Linki do podręczników Intela i mnóstwa innych dobrych rzeczy na stronie informacyjnej wiki tagów x86

Innym przypadkiem bezsensownego repprefiksu, który staje się nową instrukcją dla nowych procesorów: lzcntjest F3 0F BD /r. Na procesorach, które nie obsługują tej instrukcji (brakuje flagi funkcji LZCNT w ich CPUID), dekoduje jako rep bsr, który działa tak samo jak bsr. Więc na starych procesorach generuje 32 - expected_resulti jest niezdefiniowany, gdy wartość wejściowa wynosiła zero.

Ale tzcnti bsfrobią to samo z niezerowymi wejściami, więc kompilatory mogą i używają tzcntnawet wtedy, gdy nie ma gwarancji, że docelowy procesor będzie go uruchamiał jako tzcnt. Procesory AMD są szybkie tzcnti wolne bsf, a na Intelu oba są szybkie. O ile nie ma to znaczenia dla poprawności (nie polegasz na ustawianiu flag ani na pozostawianiu niezmodyfikowanego zachowania celu w przypadku input = 0), tzcntpomocne jest dekodowanie go tak, jak na procesorach, które go obsługują.


Jeden przypadek bezsensownego repprefiksu, który prawdopodobnie nigdy nie będzie dekodował inaczej: rep retjest używany domyślnie przez gcc, gdy celujemy w "ogólne" procesory (tj. Nie jest celowany w konkretny procesor z -marchlub -mtunei nie jest przeznaczony dla AMD K8 lub K10). Miną dekady, zanim ktokolwiek może stworzyć procesor, który dekoduje rep retjak cokolwiek innego niż ret, ponieważ jest obecny w większości plików binarnych w większości dystrybucji Linuksa. Zobacz Co oznacza „rep ret”?

Peter Cordes
źródło
3
repPrefiks został również wykorzystywane przez firmy Intel, aby dodać blokady elizja.
Paul A. Clayton
Przedrostki, które nie dotyczą instrukcji, są ignorowane. Wspomniano jednak, że powtarzanie prefiksów ( F2Hi F3H) zastrzeżone i może spowodować nieprzewidywalne zachowanie w tabeli 11-3. Wpływ prefiksów na instrukcje SSE, SSE2 i SSE3 . Tak więc aplikacja prefiksu jest ignorowana dla niektórych instrukcji, a nie dla wszystkich. Czy więc ta funkcja jest uważana za nieudokumentowaną?
St.Antario
2
@ St.Antario: Sformułowali to w ten sposób, ponieważ przyszłe procesory mogą rozpoznać to jako część jakiejś nowej instrukcji. Tak było na wszystkich prawdziwych procesorach, a kiedy już ustalą kodowanie f3 xx, dokumentują, jak działa na starszych procesorach.
Peter Cordes
1
Prefiksy (inne niż lock), które nie dotyczą instrukcji, są w praktyce ignorowane przez istniejące procesory. Udokumentowano, że rep movbepowoduje #UD, więc repnie zawsze jest ignorowane. Nawet jeśli nie dotyczy instrukcji w sensie określonym we REP/REPE/REPZ/REPNE/REPNZwpisie ręcznym.
St.Antario
2
@ St.Antario: Interesujące! Generalnie jednak w przypadku starszych instrukcji nieposiadające zastosowania przedrostki są ignorowane. Wprowadzając nową instrukcję, można dodać bardziej rygorystyczne zasady, jeśli zechcą. IDK, dlaczego wybraliby to w tym konkretnym przypadku.
Peter Cordes