Wenn Ingenieure eine Befehlssatzarchitektur entwerfen, befolgen sie, wenn vorhanden, welche Prozedur oder welches Protokoll, um bestimmte Binärcodes als Anweisungen zu kennzeichnen. Wenn ich beispielsweise eine ISA habe, die besagt, dass 10110 eine Ladeanweisung ist, woher stammt diese Binärzahl? Wurde es aus einer Statustabelle für eine Zustandsmaschine modelliert, die eine Ladeoperation darstellt?
Bearbeiten: Nach mehr Recherche glaube ich, was ich zu fragen versuche, betrifft, wie die Opcodes für die verschiedenen CPU-Anweisungen zugewiesen sind. ADD kann mit einem Opcode von 10011 gekennzeichnet sein. Ein Ladebefehl könnte als 10110 bezeichnet werden. Welcher Denkprozess wird durchgeführt, um diese binären Operationscodes für den Befehlssatz zuzuweisen?
quelle
Antworten:
In vielen Fällen ist die Auswahl ziemlich willkürlich oder basiert auf "wo immer es am besten passt", wenn ISAs im Laufe der Zeit wachsen. Der MOS 6502 ist jedoch ein wunderbares Beispiel für einen Chip, bei dem das ISA-Design stark beeinflusst wurde, indem versucht wurde, so viel wie möglich aus den begrenzten Transistoren herauszupressen.
Schauen Sie sich dieses Video an, in dem erklärt wird, wie der 6502 rückentwickelt wurde , insbesondere ab 34:20 Uhr.
Der 6502 ist ein 8-Bit-Mikroprozessor, der 1975 eingeführt wurde. Obwohl er 60% weniger Gates hatte als der Z80, war er doppelt so schnell, und obwohl er eingeschränkter war (in Bezug auf Register usw.), machte er dies mit einem wett eleganter Befehlssatz.
Es enthält nur 3510 Transistoren, die von einem kleinen Team von Personen von Hand herausgezogen wurden , die über einige große Plastikfolien krabbelten, die später optisch verkleinert wurden und die verschiedenen Schichten des 6502 bildeten.
Wie Sie unten sehen können, übergibt der 6502 den Anweisungs-Opcode und die Zeitsteuerungsdaten an den Decodierungs-ROM und übergibt sie dann an eine "Zufallssteuerungslogik" -Komponente, deren Zweck wahrscheinlich darin besteht, die Ausgabe des ROM in bestimmten komplexen Situationen zu übersteuern.
Um 37:00 Uhr im Video sehen Sie eine Tabelle des Decoder-ROM, die zeigt, welche Bedingungen die Eingänge erfüllen müssen, um für einen bestimmten Steuerausgang eine "1" zu erhalten. Sie finden es auch auf dieser Seite .
Sie können sehen, dass die meisten Dinge in dieser Tabelle Xs in verschiedenen Positionen haben. Nehmen wir zum Beispiel
Dies bedeutet, dass die ersten 3 Bits des Opcodes 011 sein müssen und G 2 sein muss; Das ist alles, was zählt. In diesem Fall wird die Ausgabe mit dem Namen RORRORA auf "true" gesetzt. Alle ROR-Opcodes beginnen mit 011; Es gibt aber auch andere Anweisungen, die mit 011 beginnen. Diese müssen wahrscheinlich von der "Zufallssteuerlogik" herausgefiltert werden.
Grundsätzlich wurden Opcodes so ausgewählt, dass Anweisungen, die dasselbe tun mussten, über ihr Bitmuster hinweg etwas gemeinsam hatten. Sie können dies sehen, indem Sie sich eine Opcode-Tabelle ansehen . Alle ODER-Anweisungen beginnen mit 000, alle Speicheranweisungen beginnen mit 010, alle Anweisungen, die eine Nullseitenadressierung verwenden, haben die Form xxxx01xx. Natürlich scheinen einige Befehle nicht "zu passen", da das Ziel nicht ein vollständig reguläres Opcode-Format ist, sondern ein leistungsfähiger Befehlssatz. Und deshalb war die "Zufallssteuerlogik" notwendig.
Die oben erwähnte Seite besagt, dass einige der Ausgabezeilen im ROM zweimal vorkommen. "Wir gehen davon aus, dass dies geschehen ist, weil sie nicht die Möglichkeit hatten, die Ausgabe einer Zeile dahin zu leiten, wo sie wollten, sodass sie dieselbe Zeile an eine andere stecken Lage wieder. " Ich kann mir vorstellen, dass die Ingenieure diese Tore einzeln von Hand zeichnen und plötzlich einen Konstruktionsfehler bemerken und versuchen, einen Weg zu finden, um einen Neustart des gesamten Prozesses zu vermeiden.
quelle
Es kommt darauf an, wie alt die ISA ist.
In den Anfängen des Hand-Designs und noch mehr, als CPUs aus diskreter Logik zusammengesetzt wurden, wäre das Logik-Design an erster Stelle gestanden und weitgehend minimiert worden, und dann wären die ISA-Bitmuster die Werte gewesen, die erforderlich waren, um dies minimal zu machen logische Arbeit.
So kann es ein bestimmtes Muster von Steuersignalen geben, die es einigen Multiplexern ermöglichen, den ALU-Ausgang mit dem Eingang der GP-Registerdatei zu verbinden, einige weitere Steuersignale, die die ALU anweisen, UND, ODER usw. zu addieren, zu subtrahieren und einige Adressbits in die Registerdatei. Diese drei Signalgruppen bilden Felder innerhalb des Befehls. Jede Gruppe wird zusammengehalten, und ihre detaillierte Bedeutung ergibt sich aus dem Entwurf für diese Einheit (ALU usw.), aber die Gruppen können in beliebiger Reihenfolge sein, bis Sie den Befehlsdecoder entwerfen. (Der x86 ist alt genug, dass Sie einiges davon erkennen können, wenn Sie an der richtigen Stelle suchen - es war kein völlig neues Design, sondern stammt aus dem älteren 8080)
Spätere ISAs können "aufgeräumt" und regelmäßiger und benutzerfreundlicher gestaltet werden, wobei Hardware zwischen ihnen und den eigentlichen Steuersignalen auf Hardwareebene zu übersetzen ist, manchmal über "Mikrocode". Diese werden als "CISC" oder "Complex Instruction Set Coding" bezeichnet. Das x86 "Rep" -Anweisungspräfix ist ein einfaches Beispiel dafür - es bewirkt, dass die folgende Anweisung mehrmals wiederholt wird, um das Schreiben einer FOR-Schleife zu vermeiden.
Noch später (in den 1980er Jahren) kam eine Bewegung zurück zu einer einfacheren Art der direkten Codierung (RISC - Reduced Instruction Set Coding), die Sie in den ARM-Prozessoren sehen können. Ausschlaggebend dafür war die geringe Größe der ASICs zu dieser Zeit und der Wunsch, 32-Bit-CPUs auf ihnen zu installieren. Daher gab es keine freie Kapazität für komplexe Befehlssatzdecoder, um die gesamte CPU auf etwa 20.000 Gates zu verkleinern. (Es gab auch eine vorübergehende Leistungssteigerung, weil die Leute noch keine Techniken entwickelt hatten, um CISC-Decoder schnell zu machen - das kam 1995 mit dem Pentium Pro)
Und heutzutage spielt es keine Rolle - CPUs lesen mehrere Anweisungen auf einmal und verwenden Millionen von Transistoren, um sie zu dekodieren, neu zu ordnen und so viele wie möglich gleichzeitig auszuführen, um Programme zu beschleunigen, die für die ältesten geschrieben wurden Stil von ISA.
quelle
Wenn Sie ähnliche Anweisungen gruppieren, entstehen Muster. Dies ist in ARM sehr offensichtlich, wo das ISA-Handbuch tatsächlich anzeigt, welches Bit eines Befehlsworts der Funktion, der Registerauswahl usw. entspricht. Es kann jedoch auch auf X86 geschlossen werden .
Letztendlich geht der "Funktions" -Teil von Opcodes in einen Binär-zu-Eins-Hot-Decoder, der tatsächlich eine bestimmte Funktion oder Sequenz von Pipeline-Operationen aktiviert. Sie beziehen sich normalerweise nicht auf den Inhalt einer Zustandsmaschine, es sei denn, es handelt sich um Befehle variabler Länge, für deren Dekodierung eine Zustandsmaschine erforderlich ist.
quelle
Irgendwann setzte sich jemand und definierte sie.
Ein guter ISA macht den Decoder so einfach wie möglich.
Zum Beispiel könnten Sie mit einem ALU-Befehl einige Bits des Opcodes direkt in die Steuerleitungen der ALU senden lassen.
quelle
Normalerweise teilen Sie Ihren ISA in Funktionsgruppen auf. Es ist sinnvoll (entweder für die Logikoptimierung oder um aufgeräumt zu sein), dass komplementäre Paare durch einen einzelnen Bitwechsel (Laden gegen Speichern) unterschieden werden und dass Sie eine Hierarchie von Bits haben, die sich auf den Decodierungsentscheidungsbaum auswirkt.
Letztendlich hat eine willkürliche Zuweisung von Bits für den Funktionsblock (im Gegensatz zum Platzieren der 'Daten'-Felder in der Anweisung) nur einen geringen Einfluss auf Ihre gesamte Entwurfseffizienz - aber Sie haben viele Möglichkeiten, wie Sie vorgehen müssen Optimieren Sie Ihre ISA-Codierung, je nachdem, was Sie für einen wichtigen Parameter halten.
quelle
Befehlskodierung ist ein hässlicher Kompromiss zwischen.
Vereinfachen Sie die Dekodierung. Dazu benötigen Sie einen einfachen Satz von Feldern, von denen jedes separat dekodiert und an einen separaten Teil der Ausführungs-Engine weitergeleitet werden kann.
Packen Sie so viele Funktionen wie möglich in ein begrenztes Anweisungswort. Dies führt zu Dingen wie speziellen Konstantenformaten, die eine Vielzahl gängiger Zahlen codieren können.
Vorwärts- und Rückwärtskompatibilität. Wenn Sie jedem möglichen Opcode eine Funktion zuweisen, haben Sie keinen Raum mehr, um die Architektur später zu erweitern. Wenn Sie eine vorhandene Architektur erweitern, müssen Sie Ihre neuen Anweisungen in die Ersatz-Opcodes einfügen.
quelle
Randy Hyde ist exzellent (wenn auch etwas veraltet). The Art of Assembly wird im x86-Befehlssatz ausführlich in Kapitel 3.3.4, Steuergerät und Befehlssätze, und in den folgenden Abschnitten beschrieben .
Er zeigt dann recht eingängig und ausführlich, wie die ersten Stecker für die Anweisung stehen, die nächsten Stecker codieren Quelle und Ziel. Natürlich "stopft" heute niemand mehr, aber für die wirklich alten ISAs machen die Bits im Opcode im Grunde den gleichen Job wie die Stecker zuvor.
Am Ende haben Sie ungefähr Folgendes:
quelle