Odpowiedź @jalfa obejmuje większość powodów, ale jest jeden interesujący szczegół, o którym nie wspomina: wewnętrzny rdzeń podobny do RISC nie jest zaprojektowany do uruchamiania zestawu instrukcji czegoś takiego jak ARM / PPC / MIPS. Podatek od x86 jest płacony nie tylko w energochłonnych dekoderach, ale w pewnym stopniu w całym rdzeniu. tj. nie chodzi tylko o kodowanie instrukcji x86; to każda instrukcja z dziwną semantyką.
Załóżmy, że Intel stworzył tryb operacyjny, w którym strumień instrukcji był czymś innym niż x86, z instrukcjami, które były bardziej odwzorowane na Uops. Udawajmy również, że każdy model procesora ma własny ISA dla tego trybu, więc nadal mogą zmieniać elementy wewnętrzne, kiedy chcą, i wystawiać je z minimalną ilością tranzystorów do dekodowania instrukcji tego alternatywnego formatu.
Przypuszczalnie nadal miałbyś tylko taką samą liczbę rejestrów odwzorowanych na stan architektury x86, więc systemy operacyjne x86 mogą zapisywać / przywracać je na przełącznikach kontekstowych bez użycia zestawu instrukcji specyficznych dla procesora. Ale jeśli odrzucimy to praktyczne ograniczenie, tak, moglibyśmy mieć kilka więcej rejestrów, ponieważ możemy użyć ukrytych rejestrów tymczasowych zwykle zarezerwowanych dla mikrokodu 1 .
Gdybyśmy mieli tylko alternatywne dekodery bez zmian w późniejszych etapach potoku (jednostkach wykonawczych), ten ISA nadal miałby wiele ekscentryczności x86. Nie byłaby to zbyt ładna architektura RISC. Żadna pojedyncza instrukcja nie byłaby bardzo złożona, ale niektóre z innych szaleństw x86 wciąż by tam były.
Na przykład: przesunięcia w lewo / w prawo pozostawiają niezdefiniowaną flagę przepełnienia, chyba że liczba przesunięć wynosi jeden, w którym to przypadku OF = zwykłe wykrywanie przepełnienia ze znakiem. Podobne szaleństwo dla rotacji. Jednak ujawnione instrukcje RISC mogą zapewniać przesunięcia bez flag i tak dalej (pozwalając na użycie tylko jednego lub dwóch z wielu uopsów, które zwykle wchodzą w skład niektórych złożonych instrukcji x86). Więc to tak naprawdę nie jest głównym kontrargumentem.
Jeśli zamierzasz stworzyć zupełnie nowy dekoder dla RISC ISA, możesz wybrać i wybrać części instrukcji x86, które mają być ujawnione jako instrukcje RISC. To nieco łagodzi specjalizację x86 rdzenia.
Kodowanie instrukcji prawdopodobnie nie będzie miało stałego rozmiaru, ponieważ pojedyncze Uops mogą pomieścić dużo danych. O wiele więcej danych, niż ma to sens, jeśli wszystkie insny mają ten sam rozmiar. Pojedynczy uop z mikro-fuzją może dodać natychmiastowy 32-bitowy i operand pamięci, który używa trybu adresowania z 2 rejestrami i 32-bitowym przesunięciem. (W SnB i nowszych, tylko jednorejestrowe tryby adresowania mogą łączyć się z operacjami ALU).
uops są bardzo duże i niezbyt podobne do instrukcji ARM o stałej szerokości. Zestaw instrukcji 32-bitowych o stałej szerokości może załadować tylko 16-bitowe natychmiastowo, więc ładowanie adresu 32-bitowego wymaga pary natychmiastowego ładowania - niska połowa / ładowanie - wysoka. x86 nie musi tego robić, co pomaga nie być strasznym, ponieważ tylko 15 rejestrów GP ogranicza możliwość utrzymywania stałych w rejestrach. (15 to duża pomoc przy 7 rejestrach, ale ponowne podwojenie do 31 pomaga o wiele mniej, myślę, że znaleziono jakąś symulację. RSP zwykle nie jest ogólnym celem, więc bardziej przypomina 15 rejestrów GP i stos.)
Podsumowanie TL; DR:
W każdym razie ta odpowiedź sprowadza się do „zestawu instrukcji x86 jest prawdopodobnie najlepszym sposobem zaprogramowania procesora, który musi być w stanie szybko wykonywać instrukcje x86”, ale miejmy nadzieję, że rzuca trochę światła na przyczyny.
Wewnętrzne formaty UOP w interfejsie użytkownika i zapleczu
Zobacz także Mikro fuzja i tryby adresowania dla jednego przypadku różnic w tym, co mogą reprezentować formaty uop front-end i back-end na procesorach Intela.
Przypis 1 : Istnieje kilka „ukrytych” rejestrów używanych jako tymczasowe przez mikrokod. Nazwy tych rejestrów są zmieniane tak samo, jak rejestry architektury x86, więc instrukcje multi-uop mogą być wykonywane poza kolejnością.
np. xchg eax, ecx
na procesorach Intela dekoduje jako 3 uopsy ( dlaczego? ), a naszym najlepszym przypuszczeniem jest to, że są to pliki Uops podobne do MOV tmp = eax; ecx=eax ; eax=tmp;
. W tej kolejności, ponieważ mierzę opóźnienie kierunku dst-> src przy ~ 1 cyklu, w porównaniu z 2 w drugą stronę. A te ruchy nie są zwykłymi mov
instrukcjami; nie wydają się być kandydatami do eliminacji ruchu z zerowym opóźnieniem.
Zobacz także http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/, gdzie można znaleźć wzmiankę o próbie eksperymentalnego pomiaru wielkości PRF i konieczności uwzględnienia fizycznych rejestrów używanych do przechowywania stanu architektonicznego, w tym rejestrów ukrytych.
W interfejsie użytkownika za dekoderami, ale przed etapem wydawania / zmiany nazwy, który zmienia nazwy rejestrów na plik rejestru fizycznego, wewnętrzny format uop wykorzystuje numery rejestrów podobne do numerów rejestrów x86, ale z miejscem na adresowanie tych ukrytych rejestrów.
Format uop jest nieco inny w rdzeniu niesprawnym (ROB i RS), czyli zapleczu (po etapie wydania / zmiany nazwy). Każdy zbiór rejestrów fizycznych int / FP ma 168 wpisów w Haswell , więc każde pole rejestru w uop musi być wystarczająco szerokie, aby zaadresować taką liczbę.
Ponieważ program do zmiany nazwy znajduje się w HW, prawdopodobnie lepiej byłoby go używać, zamiast przesyłać statycznie zaplanowane instrukcje bezpośrednio do zaplecza. Więc moglibyśmy pracować z zestawem rejestrów tak dużym jak rejestry architektoniczne x86 + tymczasowe elementy mikrokodu, nie więcej.
Back-end jest zaprojektowany do pracy z front-endowym renamerem, który unika zagrożeń WAW / WAR, więc nie mogliśmy go używać jako procesora w zamówieniu, nawet gdybyśmy chcieli. Nie ma blokad do wykrywania tych zależności; to jest obsługiwane przez wydanie / zmianę nazwy.
Byłoby fajnie, gdybyśmy mogli wprowadzić uopsy do zaplecza bez wąskiego gardła na etapie wydania / zmiany nazwy (najwęższy punkt w nowoczesnych potokach Intela, np. 4-szerokie w Skylake w porównaniu z 4 ALU + 2 obciążenia + 1 port magazynu w zaplecze). Ale jeśli to zrobiłeś, nie sądzę, abyś mógł statycznie zaplanować kod, aby uniknąć ponownego wykorzystania rejestru i nadepnięcia na wynik, który jest nadal potrzebny, jeśli brak pamięci podręcznej zatrzymał ładowanie na długi czas.
Tak więc prawie musimy podać Uops do etapu wydania / zmiany nazwy, prawdopodobnie omijając tylko dekodowanie, a nie pamięć podręczną uop lub IDQ. Następnie otrzymujemy normalne wykonanie OoO z rozsądnym wykrywaniem zagrożeń. Tablica alokacji rejestrów jest zaprojektowana tylko do zmiany nazwy 16 + kilku rejestrów całkowitych na 168-wejściową liczbę całkowitą PRF. Nie mogliśmy oczekiwać, że HW zmieni nazwę większego zestawu rejestrów logicznych na taką samą liczbę rejestrów fizycznych; to wymagałoby większego RAT.