Herdware schrieb:
Die echten Altlasten beschränken sich doch eigentlich nur auf den vorgeschalteten Decoder, der seit den PentiumPro-Zeiten die x86-Befehle in MicroOps aufteilt.
Oh, da gibt es ein paar mehr Altlasten, als nur diesen Decoder, dafür müsste man aber mal etwas tiefer in die Materie eintauchen und ein Asselembler-Erfahrungen von CISC und RISC-Prozessoren mit bringen.
Auch bei modernen ARM-Prozessoren sitzt heute ein Decoder, der die meisten Befehle noch mal in MikroOps aufsplittet. Nur geht das wesentlich schneller und einfacher, weil die meisten ARM-Befehle eine feste Breite haben und in der Regel bereits Atomar sind.
Das ist aber nur ein Teil: Die Probleme liegen auch bereits in IA32 selbst und den Zeitraum in dem die Grundzüge des x86 entstanden sind, da kommen wir aber nun in dem Bereich, in dem man sich noch mehr mit Prozessoren beschäftigen muss und auch die Gedankengänge hinter ARM und x86 mal hören musste.
Herdware schrieb:
Überall sonst dürfte die Entwicklung der x86-CPUs grundsätzlich ähnlich dynamisch verlaufen sein, wie bei der ursprünglich ja auch aus den 80ern stammenden ARM-Architektur.
Na, dann würde ich ja an der Stelle dir mal empfehlen in eine Universitätsbibliothek zu gehen und dir Bücher über die Entwicklung der IT in den 50er, 60er, 60er und 80er zu holen und dir anzusehen, welchen Einfluss zum Beispiel die Halbleiterfertigung in den 60er- und 70er auf das CPU-Design hatten und wie schnell sich da dann das Bild auch mal gedreht hat, nur weil plötzlich es technisch es möglich war.
x86/IA32 hat einen CISC-Befehlssatz, weil man damals Prozessoren noch primär über Assembler programmiert wurde und man dem entsprechend eher auf Lesbarkeit und Einfachheit der Befehle geachtet hat und man gewisse Aktionen hinter den Befehlen versteckt hat. Erst in den 70er, als Festplatten und ebenso wiederbeschreibbare Speichermedien relevant wurden und damit auch der Compiler beflügelt wurde, wurde RISC wirklich eine Alternative, weil RISC-Assembler für Menschen quasi schnell unverständlich und hoch komplex wid.
Dazu kommt, dass man in den Anfängen in die CPUs und damit verbunde in die ISAs nicht mehr Register als notwendig aufzunehmen und diese oft noch an gewisse Funktionen gebunden war. Denn Register benötigten Transitoren und Register, die mehre ALUs füttern können, verbrauchen noch mehr Tranistoren, als hat man sie bei x86 auf das nötigste Reduziert.
Ja, ARM ist in den 80er entsanden, nur ließ dir mal Interviews mit den Entwicklern von ARM durch und welche Erkenntnisse es damals schon gab: Je mehr man an Daten direkt in den Registern halten kann, um so schneller kann eine CPU arbeiten. Dazu kommt, dass die Daten in den Registern zu halten weniger Energie benötigt, als die Daten aus den Caches und noch schlimmer aus den RAM zu holen oder dorthin zu schieben.
Moderne x86-CPUs haben entweder - 8 oder 16 allgemeine Register im "INT"-Core und 16 Register im FPU-Teil oder - AVX512 - 32. ARMv8 sieht 31 für den eigentlichen Kern vor und 32 für Neon/SVE - bald auch SVE2. Sehr gute Compiler können alleine Anhand dieser Anzahl an Register sehr viele Daten möglichst lange auch in den Registern halten, bevor Daten aus den Caches geladen werden müssen in die Register.
Gute OoO-Algorithmen mit passender Fluss-Analyse und dazu Registerrenames minimieren den Zugriff auf die Caches und erst recht den RAM. Nur braucht man dafür auch eine entsprechende Anzahl an Register: Ein Grund warum Intel quasi seit MMX die Register Anzahl der FPU erst von 8 auf 16 und nun 32 Erweiterte oder warum AMD mit x64 zumindest 8 allgemeine Register eingeführt hat.
Herdware schrieb:
Intern hat eine aktuelle x86-CPU nur noch herzlich wenig mit einem 8086/8088 aus den 70ern gemein.
Auf Hardware ebene mag das zwar durchaus hinkommen, nur die ISA stammt immer noch aus den 70er mit all den damaligen Überlegungen um Kosten zu sparen und die Limitierungen der ISA kann man nicht einfach eliminieren. Diese sind immer noch vorhanden und diese Limitierungen bestimmen bis Heute auch das Design der Kerne.
Sieht man sich sich den Firestorm-Kern an, dann kommt da ein Decoder, der 8 Befehle pro Takt decodieren kann, dahinter ist ein Backend mit 6 ALUs + DIV-ALU, macht also 7 ALUs, 2 Load-Einheiten, 1 Sore-Einheit und eine Load/Store-Kombi. Dazu 4 * 128Bit Neon.
Zen 3 kommt auf 4 ALUs, 3 AGUs und damit auf 3 Load + 2 Store pro Takt, Apple kann entweder 3 Load + 1 Store oder 2 Load + 2 Store machen und versorgt damit ein deutlich breiteres Backend. Warum? Weil man dank der "Masse" an Register wesentlich seltener in den Cache und in RAM muss.
Und da sind wir wirder bei den 70er und den 80er: In den 70er waren Transitoren "Teuer" und jedes unnötige Register war nicht gerne gesehen. In den 80er hat sich das geändert, denn man wusste, dass Zugriffe auf Caches und Speicher und damit das verbundene Warte nicht nur Energie kostet, sondern auch Zeit.