Orthogonaler Befehlssatz - Orthogonal instruction set

In der Computertechnik ist ein orthogonaler Befehlssatz eine Befehlssatzarchitektur, bei der alle Befehlstypen alle Adressierungsmodi verwenden können . Es ist " orthogonal " in dem Sinne, dass der Befehlstyp und der Adressierungsmodus unabhängig voneinander variieren. Ein orthogonaler Befehlssatz legt keine Einschränkung fest, die erfordert, dass ein bestimmter Befehl ein bestimmtes Register verwendet, so dass sich die Befehlsfunktionalität kaum überlappt.

Orthogonalität wurde in den 1970er Jahren als Hauptziel für Prozessordesigner angesehen, und der VAX-11 wird häufig als Benchmark für dieses Konzept verwendet. Die Einführung der RISC- Designphilosophie in den 1980er Jahren kehrte jedoch den Trend zu mehr Orthogonalität erheblich um. Moderne CPUs simulieren häufig die Orthogonalität in einem Vorverarbeitungsschritt, bevor die eigentlichen Aufgaben in einem RISC-ähnlichen Kern ausgeführt werden.

Grundlegendes Konzept

Im Kern arbeiten alle Allzweckcomputer auf dieselbe zugrunde liegende Weise. In einem Hauptspeicher gespeicherte Daten werden von der Zentraleinheit (CPU) in einen schnellen temporären Speicher (z. B. CPU-Register ) eingelesen, bearbeitet und dann in den Hauptspeicher zurückgeschrieben. Der Speicher besteht aus einer Sammlung von Datenwerten, die als Zahlen codiert sind und auf deren Adressen verwiesen wird, sowie einem numerischen Wert. Dies bedeutet, dass dieselben Operationen, die auf die Daten angewendet werden, auf die Adressen selbst angewendet werden können. Während der Bearbeitung können Daten vorübergehend in Prozessorregistern gespeichert werden. Dies sind Scratchpad-Werte, auf die sehr schnell zugegriffen werden kann. Register werden beispielsweise verwendet, wenn Zahlenfolgen zu einer Summe addiert werden.

Einzelbefehl, einzelner Operand

In frühen Computern verwendete die Befehlssatzarchitektur (ISA) häufig ein einzelnes Register. In diesem Fall wurde es als Akkumulator bezeichnet . Die Anweisungen enthielten eine Adresse für den Operanden. Beispielsweise würde ein Befehl die CPU veranlassen, die an dieser Adresse gefundene Nummer im Speicher abzurufen und sie dann zu dem Wert hinzuzufügen, der sich bereits im Akkumulator befindet. Dieses sehr einfache Beispiel ISA hat ein "Ein-Adressen-Format", da jeder Befehl die Adresse der Daten enthält. ADD address

Ein-Adressen-Maschinen haben den Nachteil, dass selbst einfache Aktionen wie das Hinzufügen mehrere Anweisungen erfordern, von denen jede wenig Speicherplatz beansprucht und Zeit zum Lesen benötigt. Betrachten Sie die einfache Aufgabe, zwei Zahlen 5 + 4 zu addieren. In diesem Fall müsste das Programm den Wert 5 mit der Anweisung in den Akkumulator laden , die Anweisung verwenden, die auf die Adresse für die 4 zeigt, und schließlich das Ergebnis speichern , 9, zurück zu einem anderen Speicherort. LOAD addressADD addressSAVE address

Einzelbefehl, mehrere Operanden

Weitere Verbesserungen können gefunden werden, indem beispielsweise die Adresse beider Operanden in einem einzigen Befehl angegeben wird . Solche ISAs im "Zwei-Adressen-Format" sind sehr verbreitet. Man kann das Konzept weiter auf ein "Drei-Adressen-Format" erweitern, bei dem das auch zu einem erweiterten gefaltet wird . ADD address 1, address 2SAVEADD address 1, address 2, address of result

Es ist häufig der Fall, dass das grundlegende Computerwort viel größer ist als erforderlich, um nur den Befehl und eine Adresse aufzunehmen, und in den meisten Systemen gibt es übrig gebliebene Bits, die verwendet werden können, um eine Konstante anstelle einer Adresse zu halten. Anweisungen können weiter verbessert werden, wenn sie es ermöglichen, einen der Operanden durch eine Konstante zu ersetzen. Zum Beispiel beseitigt einen Speicherzyklus, und ein anderer. ADD address 1, constant 1ADD constant 1, constant 2

Mehrere Daten

Weitere Komplexität ergibt sich, wenn man gemeinsame Muster betrachtet, in denen auf Speicher zugegriffen wird. Ein sehr häufiges Muster besteht darin, dass eine einzelne Operation auf eine große Menge ähnlicher Daten angewendet werden kann. Zum Beispiel möchte man vielleicht 1.000 Zahlen addieren. In einem einfachen Zwei-Adressen-Format von Anweisungen gibt es keine Möglichkeit, die Adresse zu ändern, sodass 1.000 Ergänzungen in der Maschinensprache geschrieben werden müssen . ISAs beheben dieses Problem mit dem Konzept der indirekten Adressierung , bei der die Adresse des nächsten Datenpunkts keine Konstante ist, sondern selbst im Speicher gehalten wird. Dies bedeutet, dass der Programmierer die Adresse ändern kann, indem er eine Addition an diesem Speicherort durchführt. ISAs umfassen häufig auch die Möglichkeit, eine Adresse von einem anfänglichen Ort zu versetzen, indem ein Wert hinzugefügt wird, der in einem seiner Register, in einigen Fällen einem speziellen Indexregister, gespeichert ist . Andere führen diesen Zusatz automatisch als Teil der Anweisungen aus, die ihn verwenden.

Die Vielzahl der Adressierungsmodi führt zu einer Fülle leicht unterschiedlicher Anweisungen. In Anbetracht einer ISA mit einer Adresse für nur einen einzelnen Befehl ADD haben wir jetzt viele mögliche "Adressierungsmodi":

  • Sofort (konstant): - Addiert den konstanten Wert zum Ergebnis im Akkumulator ADD.C constant 1
  • Direkte Adresse: - Addieren Sie den an Adresse 1 gespeicherten Wert ADD.A address 1
  • Speicher indirekt: - Lesen Sie den Wert in Adresse 1, verwenden Sie diesen Wert als andere Adresse und addieren Sie diesen Wert ADD.M address 1

Viele ISAs haben auch Register, die sowohl für Adressierungs- als auch für mathematische Aufgaben verwendet werden können. Dies kann in einem Ein-Adress-Format verwendet werden, wenn ein einzelnes Adressregister verwendet wird. In diesem Fall stehen eine Reihe neuer Modi zur Verfügung:

  • Direkt registrieren: - Addieren Sie den Wert, der in der Adresse in Register 1 gespeichert ist ADD.R register 1
  • Verschiebung: - Fügen Sie die Konstante zum Adressregister hinzu und fügen Sie dann den Wert hinzu, der an dieser resultierenden Stelle im Speicher gefunden wurde ADD.D constant 1
  • Index: - Fügen Sie den Wert in Register 1 zum Adressregister hinzu, um eine neue Adresse zu erstellen, und fügen Sie dann den Wert an dieser Stelle zum Akkumulator hinzu ADD.I register 1
  • Autoindex: - wie im Index-Fall, erhöht jedoch automatisch die Adresse ADD.AI register 1

Orthogonalität

Orthogonalität ist das Prinzip, dass jeder Befehl jeden unterstützten Adressierungsmodus verwenden kann. Wenn in diesem Beispiel die Version für die direkte Adressierung von ADD verfügbar ist, sollten dies auch alle anderen sein. Der Grund für dieses Design ist nicht ästhetisch. Ziel ist es, die Gesamtgröße des Objektcodes eines Programms zu reduzieren . Durch die Bereitstellung einer Vielzahl von Adressierungsmodi ermöglicht der ISA dem Programmierer, denjenigen auszuwählen, der genau zu diesem Zeitpunkt den Anforderungen seines Programms entspricht, und dadurch die Notwendigkeit zu verringern, mehrere Anweisungen zu verwenden, um dasselbe Ziel zu erreichen. Dies bedeutet, dass die Gesamtzahl der Anweisungen reduziert wird, was sowohl Speicherplatz spart als auch die Leistung verbessert. Orthogonalität wurde oft als sehr "biteffizient" beschrieben.

Da das ultimative Ende des orthogonalen Entwurfs einfach darin besteht, jedem Befehl zu erlauben, irgendeine Art von Adresse zu verwenden, ist das Implementieren von Orthogonalität oft einfach ein Fall des Hinzufügens von mehr Verdrahtung zwischen den Teilen des Prozessors. Es erhöht jedoch auch die Komplexität des Befehlsdecodierers, der Schaltung, die einen Befehl aus dem Speicher an der Stelle liest, auf die der Programmzähler zeigt, und dann entscheidet, wie er verarbeitet wird.

In dem oben beschriebenen Beispiel-ISA enthält der ADD.C Befehl, der eine direkte Codierung verwendet, bereits die Daten, die zum Ausführen des Befehls erforderlich sind, und es ist keine weitere Verarbeitung erforderlich. Der Decodierer sendet den Wert einfach an die arithmetische Logikeinheit (ALU). Wenn jedoch der ADD.A Befehl verwendet wird, muss die Adresse gelesen, der Wert an diesem Speicherort gelesen und dann die ALU fortgesetzt werden. Diese Reihe von Ereignissen dauert viel länger und erfordert mehr interne Schritte.

Infolgedessen kann die Zeit, die zum Ausführen verschiedener Variationen eines Befehls benötigt wird, stark variieren, was das gesamte CPU-Design komplexer macht. Daher stellt Orthogonalität einen Kompromiss im Design dar; Der Computerdesigner kann dem Programmierer mehr Adressierungsmodi anbieten, um die Codedichte zu verbessern, und zwar auf Kosten der Komplexität der CPU.

Wenn der Speicher klein und teuer war, insbesondere in der Ära des Trommelspeichers oder des Kernspeichers , war Orthogonalität sehr wünschenswert. Die Komplexität lag jedoch oft über dem, was mit der aktuellen Technologie erreicht werden konnte. Aus diesem Grund boten die meisten Maschinen aus den 1960er Jahren nur eine teilweise Orthogonalität, so viel sich die Designer leisten konnten. In den 1970er Jahren reduzierte die Einführung der Integration in großem Maßstab die Komplexität von Computerdesigns erheblich, und es entstanden vollständig orthogonale Designs. In den 1980er Jahren konnten solche Designs auf einer Single-Chip-CPU implementiert werden.

In den späten 1970er Jahren, als die ersten leistungsstarken, vollständig orthogonalen Designs auf den Markt kamen , wurde das Ziel erweitert, die Hochsprachen-Computerarchitektur , kurz HLLCA, zu werden. So wie Orthogonalität gewünscht wurde, um die Bitdichte der Maschinensprache zu verbessern, war es das Ziel von HLLCA, die Bitdichte von Hochsprachen wie ALGOL 68 zu verbessern . Diese Sprachen verwendeten im Allgemeinen einen Aktivierungsdatensatz , eine Art komplexer Stapel , in dem temporäre Werte gespeichert waren, die von den ISAs im Allgemeinen nicht direkt unterstützt wurden und unter Verwendung vieler einzelner Anweisungen der zugrunde liegenden ISA implementiert werden mussten. Durch Hinzufügen einer Unterstützung für diese Strukturen könnte das Programm direkter in die ISA übersetzt werden.

Orthogonalität in der Praxis

Der PDP-11

Der PDP-11 war im Wesentlichen orthogonal (hauptsächlich mit Ausnahme seiner Gleitkommaanweisungen). Die meisten ganzzahligen Befehle könnten entweder mit 1-Byte- oder 2-Byte-Werten arbeiten und auf Daten zugreifen, die in Registern gespeichert, als Teil des Befehls gespeichert, im Speicher gespeichert oder im Speicher gespeichert sind und auf die Adressen in Registern verweisen. Auch der PC und der Stapelzeiger könnte durch die gewöhnlichen Anweisungen beeinflusst werden alle der gewöhnlichen Daten - Modi. Der "Sofort" -Modus (fest codierte Zahlen innerhalb eines Befehls, wie z. B. ADD # 4, R1 (R1 = R1 + 4), wurde als Modus "Register indirekt, automatische Inkrementierung" implementiert und der Programmzähler (R7) als Register zur Verwendung der Referenz angegeben zur Indirektion und zur automatischen Inkrementierung.

Der PDP-11 verwendete 3-Bit-Felder für Adressierungsmodi (0-7) und Register (R0 - R5, SP, PC), sodass es (elektronisch) 8 Adressierungsmodi gab. Sofortige und absolute Adressoperanden, die die beiden Autoinkrementierungsmodi auf den Programmzähler (R7) anwenden, lieferten insgesamt 10 konzeptionelle Adressierungsmodi.

Der VAX-11

Der VAX-11 erweiterte die Orthogonalität des PDP-11 auf alle Datentypen, einschließlich Gleitkommazahlen. Anweisungen wie 'ADD' wurden in datengrößenabhängige Varianten wie ADDB, ADDW, ADDL, ADDP, ADDF zum Hinzufügen von Byte, Wort, Langwort, gepacktem BCD bzw. Gleitkomma mit einfacher Genauigkeit unterteilt. Wie der PDP-11 befanden sich der Stapelzeiger und der Programmzähler in der allgemeinen Registerdatei (R14 und R15).

Die allgemeine Form eines VAX-11-Befehls wäre:

opcode [ operand ] [ operand ]  ...

Jede Komponente besteht aus einem Byte , der Opcode aus einem Wert im Bereich von 0 bis 255 und jeder Operand aus zwei Halbbytes , wobei die oberen 4 Bits einen Adressierungsmodus und die unteren 4 Bits (normalerweise) eine Registernummer (R0 - R15) angeben ).

Im Gegensatz zu den 3-Bit-Feldern des PDP-11 führten die 4-Bit-Subbytes des VAX-11 zu 16 logischen Adressierungsmodi (0–15). Die Adressierungsmodi 0–3 waren jedoch für Sofortdaten von 6 Bit oder weniger "kurz sofort" (die 2 niederwertigen Bits des Adressierungsmodus sind die 2 höherwertigen Bits der Sofortdaten, wenn sie den verbleibenden 4 Bits vorangestellt werden in diesem Datenadressierungsbyte). Da die Adressierungsmodi 0-3 identisch waren, wurden 13 (elektronische) Adressierungsmodi erstellt. Wie beim PDP-11 wurden durch die Verwendung des Stapelzeigers (R14) und des Programmzählers (R15) insgesamt über 15 konzeptionelle Adressierungsmodi erstellt (wobei das Assembler-Programm den Quellcode in den tatsächlich benötigten Adressierungsmodus auf Basis von Stapelzeigern oder Programmzählern übersetzt).

Der MC68000 und ähnlich

Die Designer von Motorola versuchten, die Assemblersprache orthogonal zu machen, während die zugrunde liegende Maschinensprache etwas weniger war. Im Gegensatz zu PDP-11 verwendete der MC68000 (68k) separate Register, um Daten und die Adressen von Daten im Speicher zu speichern. Die ISA war insofern orthogonal, als Adressen nur in diesen Registern verwendet werden konnten, es gab jedoch keine Einschränkung, welches der Register von verschiedenen Anweisungen verwendet werden konnte. Ebenso waren die Datenregister über Anweisungen hinweg orthogonal.

Im Gegensatz dazu wurde die NS320xx- Serie ursprünglich als Single-Chip-Implementierung des VAX-11 ISA entwickelt. Obwohl sich dies aus rechtlichen Gründen ändern musste, behielt das resultierende System einen Großteil der gesamten Designphilosophie des VAX-11 bei und blieb vollständig orthogonal. Dies beinhaltete die Eliminierung der separaten Daten- und Adressregister, die im 68k gefunden wurden.

Die 8080 und folgen auf Designs

Der 8-Bit- Mikroprozessor Intel 8080 (sowie der 8085 und 8051) war im Grunde ein leicht erweitertes akkumulatorbasiertes Design und daher nicht orthogonal. Ein Assembler-Programmierer oder Compiler-Writer musste berücksichtigen, welche Operationen für jedes Register möglich waren: Die meisten 8-Bit-Operationen konnten nur mit dem 8-Bit- Akkumulator (dem A-Register) ausgeführt werden, während 16-Bit-Operationen möglich waren wird nur für den 16-Bit-Zeiger / Akkumulator (das HL-Registerpaar) ausgeführt, während einfache Operationen wie das Inkrementieren für alle sieben 8-Bit-Register möglich waren. Dies war hauptsächlich auf den Wunsch zurückzuführen, alle Opcodes ein Byte lang zu halten.

Der binärkompatible Z80 fügte später Präfixcodes hinzu, um dieser 1-Byte-Grenze zu entkommen und einen leistungsfähigeren Befehlssatz zu ermöglichen. Die gleiche Grundidee wurde für den Intel 8086 verwendet , obwohl hier keine binäre Kompatibilität mit dem 8080 versucht wurde, um radikalere Erweiterungen zu ermöglichen . Es behielt einen gewissen Grad an Nichtorthogonalität bei, um zu dieser Zeit eine hohe Codedichte zu erreichen. Die 32-Bit-Erweiterung dieser Architektur, die mit dem 80386 eingeführt wurde , war etwas orthogonaler, obwohl alle 8086-Befehle und ihre erweiterten Gegenstücke beibehalten wurden. Die verwendete Codierungsstrategie zeigt jedoch immer noch viele Spuren von 8008 und 8080 (und Z80). Beispielsweise bleiben Einzelbyte-Codierungen für bestimmte häufige Operationen wie Push und Pop von Registern und Konstanten erhalten. und der primäre Akkumulator, das EAX-Register , verwendet bei bestimmten Arten von Operationen kürzere Codierungen als die anderen Register. Beobachtungen wie diese werden manchmal zur Codeoptimierung sowohl in Compilern als auch in handgeschriebenem Code ausgenutzt .

RISC

Eine Reihe von Studien in den 1970er Jahren hat gezeigt, dass die Flexibilität, die orthogonale Modi bieten, bei tatsächlichen Problemen selten oder nie genutzt wurde. Insbesondere bei IBM wurden Spuren von Code untersucht, der auf dem System / 370 ausgeführt wird, und es wurde gezeigt, dass nur ein Bruchteil der verfügbaren Modi in tatsächlichen Programmen verwendet wurde. Ähnliche Studien, oft über die VAX, zeigten das gleiche Muster. In einigen Fällen wurde gezeigt, dass die Komplexität der Anweisungen dazu führte, dass ihre Ausführung länger dauerte als die Abfolge kleinerer Anweisungen, wobei das kanonische Beispiel hierfür die INDEX Anweisung der VAX war .

Während des gleichen Zeitraums nahmen Halbleiterspeicher rasch an Größe zu und nahmen an Kosten ab. Ihre Geschwindigkeit verbesserte sich jedoch nicht mit der gleichen Geschwindigkeit. Dies bedeutete, dass die Zeit, die für den Zugriff auf Daten aus dem Speicher benötigt wurde, im Vergleich zur Geschwindigkeit der CPUs relativ zunahm. Dies sprach für die Aufnahme von mehr Registern, wodurch die CPU mehr temporäre Werte für die Arbeit erhält. Eine größere Anzahl von Registern bedeutete, dass mehr Bits im Computerwort benötigt würden, um die Registernummer zu codieren, was darauf hindeutete, dass die Anzahl der Anweisungen selbst reduziert werden sollte, um Platz freizugeben.

Schließlich hat eine Arbeit von Andrew Tanenbaum gezeigt, dass 97% aller Konstanten in einem Programm zwischen 0 und 10 liegen, wobei 0 zwischen 20 und 30% der Gesamtzahl ausmacht. Zusätzlich sind zwischen 30 und 40% aller Werte in einem Programm Konstanten, mit einfachen Variablen (im Gegensatz zu Arrays oder dergleichen) weitere 35 bis 40%. Wenn der Prozessor ein größeres Befehlswort wie 32 Bit verwendet, können zwei Konstanten und eine Registernummer in einem einzigen Befehl codiert werden, solange der Befehl selbst nicht zu viele Bits verwendet.

Diese Beobachtungen führten dazu, dass das orthogonale Design als primäres Ziel des Prozessordesigns aufgegeben wurde und die RISC- Philosophie in den 1980er Jahren aufkam. RISC-Prozessoren haben im Allgemeinen nur zwei Adressierungsmodi: Direkt (konstant) und Register. Alle anderen Modi älterer Prozessoren werden explizit mithilfe von Lade- und Speicheranweisungen behandelt, mit denen Daten zu und von den Registern verschoben werden. Möglicherweise sind nur wenige Adressierungsmodi verfügbar, und diese Modi können variieren, je nachdem, ob sich der Befehl auf Daten bezieht oder eine Übertragung der Steuerung beinhaltet .

Anmerkungen

Verweise

  1. ^ Null, Linda; Lobur, Julia (2010). Die Grundlagen der Computerorganisation und -architektur . Jones & Bartlett Verlag. S. 287–288. ISBN   978-1449600068 .
  2. ^ Tariq, Jamil (1995), "RISC vs CISC: Warum weniger mehr ist" , IEEE Potentials (August / September) , abgerufen am 7. Mai 2019
  3. ^ "Grundlegende Computerorganisation und -design" (PDF) . Computergestütztes Labor für sensorisch-motorische Systeme.
  4. ^ a b c d e Tullsen, Dean. "Befehlssatzarchitektur" (PDF) . UCSD.
  5. ^ a b c d e f g Hennessy, John; Patterson, David (29.05.2002). Computerarchitektur: Ein quantitativer Ansatz . p. 151. ISBN   9780080502526 .
  6. ^ "Einführung in den PDP-11" . Universität von Sydney .
  7. ^ a b "PDP-11-Anweisungsreferenz" (PDF) . Universität von Toronto .
  8. ^ a b c "Ein weiterer Ansatz zur Befehlssatzarchitektur - VAX" (PDF) . Universität Bremen .
  9. ^ Veronis, Andrew (2012-12-06). Der 68000 Mikroprozessor . p. 54. ISBN   9781468466478 .
  10. ^ Tilson, Michael (Oktober 1983). "Unix auf neue Maschinen verschieben" . BYTE . p. 266 . Abgerufen am 31. Januar 2015 .
  11. ^ NS32532 . Datormuseum .
  12. ^ Patterson, DA ; Ditzel, DR (1980). "Der Fall für den reduzierten Befehlssatzcomputer". ACM SIGARCH Computerarchitektur Nachrichten . 8 (6): 25–33. CiteSeerX   10.1.1.68.9623 . doi : 10.1145 / 641914.641917 . S2CID   12034303 .
  13. ^ Tanenbaum, Andrew (1978). "Implikationen strukturierter Programmierung für die Maschinenarchitektur" . Mitteilungen der ACM . 21 (3): 237–246. doi : 10.1145 / 359361.359454 . hdl : 1871/2610 . S2CID   3261560 .