Warum hat MIPS shamt eingebunden und funct / opcode unterschieden?

15

Ich bin verwirrt, warum die MIPS-Designer 5 Bits für das Verschieben verwenden und separate Opcode- und Funktionsbits haben.

Da MIPS so RISC ist, gehe ich davon aus, dass nur mit wenigen Anweisungen verschoben werden kann. Diese 5 Bits scheinen also Speicherplatz zu verschwenden, wenn sie in die unmittelbare Umgebung gestellt werden könnten. Ich gehe davon aus, dass Opcodes und Funkt zur Unterscheidung von Anweisungen vom Typ R und I getrennt sind, aber dies könnte durch Erweitern des Opcodes um 1 Bit erfolgen. Mit diesen beiden Befehlen vom R-Typ könnte sie 22 Bits lang sein. Dies funktioniert nicht, wenn die Anweisungen I-Type und J-Type ihre unmittelbare Adresse beibehalten möchten, aber beide als unnötig erscheinen.

qwr
quelle

Antworten:

10

Hier gibt es ein paar verschiedene Kompromisse.

Zunächst möchten wir, dass die Befehle eine feste Breite (32 Bit) haben. Dies garantiert, dass die Anweisungen auf Cache-Block und Seite ausgerichtet sind, was das Vorhandensein von Cache und Seite sowie die Berechtigungsprüfungen vereinfacht.

Zweitens möchten wir, dass die verschiedenen Anweisungsfelder ( opcode/ source regs/ immediates) eine feste Breite und eine feste Position haben. Dies macht sie schneller / weniger logisch zu dekodieren und sie werden in den frühen Phasen der Pipeline benötigt. (Das destinationRegister wird erst am Ende der Pipeline benötigt, es kann sich also an verschiedenen Stellen in Rund an IAnweisungen befinden.) Die Position und Breite des functionFeldes sind etwas weniger wichtig, da dies die Funktion der ALU steuern muss, aber das ist es In der dritten Phase der Pipeline haben Sie also etwas Zeit, um bei Bedarf damit zu arbeiten.

IJJ228228IAnweisungen sind auch für Compiler / Linker-Autoren nützlich. (Auf dem SPARC, wo das unmittelbare Feld nur 12 Bits umfasste, mussten sie eine ganze spezielle load-highAnweisungsklasse mit einem unmittelbaren 20-Bit-Wert hinzufügen .)

26=64JRI

Aber das lässt ein wenig Spielraum mit den RAnweisungen. Abgesehen von dem 6-Bit-Opcode benötigen diese nur 15 zusätzliche Bits für die Registerspezifikation, was 11 Bits für den erweiterten Opcode und / oder den Verschiebebetrag übrig lässt.

Sie sollten sich das functionFeld als erweiterten Opcode für die RAnweisung vorstellen . Es gibt nur einen RBefehls-Opcode, aber es gibt 64 verschiedene Befehle functions, die der RBefehl ausführen kann.

Okay. Wir haben 60 verschiedene IAnweisungen und 64 verschiedene RAnweisungen. Wo sollen wir also die Anweisungen für die Schicht sofort platzieren?

Nun, es gibt nicht nur weniger IAnweisungen, sondern auch viel mehr Dinge, die wir mit I Anweisungen tun möchten . Denken Sie daran, dass alle Verzweigungsanweisungen Anweisungen sein müssen, Ida sie einen relativen (unmittelbaren) Versatz haben. Auch alle Lade- und Speicheranweisungen sind Iin MIPS formatiert. Und schließlich brauchen wir die Anweisung Laden-Oben-Sofort, um eine IAnweisung zu sein. Nicht nur das, sondern die RBefehle enthalten noch 5 zusätzliche nicht verwendete Bits (was wir für das unmittelbare Verschieben eines Sofortbefehls in dieser Architektur benötigen), sodass dies einen weiteren Anreiz darstellt, die Verschiebungsbefehle in spezielle (seltsame) RBefehle umzuwandeln .

Viele dieser Entscheidungen sind mehr Kunst als Wissenschaft, aber es gibt eine zugrunde liegende Logik, die erkannt werden kann. Das Hauptziel ist nicht die Anzahl der Anweisungen so klein wie möglich zu machen, ist es ein machen HochleistungsPipeline passt auf einen einzigen Chip (so dass winzige Unternehmen wie MIPS und Sun in den 1980er Jahren mit IBM und DEC konkurrieren konnten). (Der von David Patterson erfundene Name RISC ist etwas unglücklich. Er hat sich durchgesetzt, weil er niedlich war, und nicht, weil "reduzierte Anweisungen" eine genaue Beschreibung dessen sind, was die MIPS- und SPARC-Architekturen wirklich versucht haben.) Anweisungen mit fester Breite (und relativ klein, damit Sie ein besseres I-Cache-Verhalten erzielen), um das Abrufen, Blättern und Dekodieren einfacher und schneller zu machen. Sie möchten die Teile der Anweisung, die vorzeitig dekodiert werden müssen (opcode, die beiden Quellregister und das Vorzeichen sofort erweitert), um eine feste Breite und eine feste Position zu haben. Sie möchten, dass die Anweisungen so lang wie möglich sind, und Sie möchten so viele verschiedene Arten von Anweisungen, wie dies angesichts all dieser anderen Einschränkungen möglich ist.

Wandering Logic
quelle
Vielen Dank für Ihre informative Antwort, insbesondere den Teil über die Ziele der Architekturdesigner. Ich finde es interessant, MIPS mit dem MOS 6502 zu vergleichen, denn wenn ich es richtig verstehe, hatte der 6502 noch nie ein Problem (ich versuche immer noch, die Befehlsformate zu verstehen).
Qwr
1
Der 6502 war ein Mikroprozessor der ersten Generation (vor CISC), obwohl er Pipelining vorwegnahm, da er gleichzeitig mit dem Laden des nächsten Befehls ein Zurückschreiben des Registers durchführen konnte. Der 6502 hatte Byte-Opcodes, wie die meisten 8-Bit-Mikros. Eine weitere zu berücksichtigende Architektur ist der ARM, der von einer Gruppe hochrangiger Elektronikingenieure entworfen wurde, die die Berkeley RISC-Papiere gelesen und die MOS-Fabrik besucht haben und beschlossen haben, "hey, das können wir".
Pseudonym
Ich frage mich, was die Implikationen gewesen wären, wenn es ein Shamt-Bit-Muster gegeben hätte, das bedeutete: "Führe den folgenden Befehl nicht aus, sondern verwende die dafür abgerufenen 32 Bits als Quelloperanden für diesen Befehl." Alternativ oder zusätzlich frage ich mich, ob es praktisch gewesen wäre, einen angemessenen Teil des Opcode-Speicherplatzes für Paare einfacher unterbrechungsfreier Anweisungen zu haben - ein Konzept wie Thumb, das jedoch frei mit 32-Bit-Anweisungen und ohne die Fähigkeit dazu durchsetzbar ist direkt zur zweiten Anweisung eines Wortes springen?
Supercat
5

Um die MIPS I-Befehlsformate zu verstehen, müssen Sie die MIPS-Pipeline verstehen und auch auf die CPU-Implementierungstechnologie von 1985 zurückblicken ID-Phase direkt nach IF.

Für den Zweck einer Anweisung vom Typ R muss die ID-Stufe die folgenden Aufgaben ausführen:

  1. Stellen Sie fest, dass es sich tatsächlich um eine Anweisung vom Typ R handelt.
  2. In diesem Fall weisen Sie die Registerdatei an, Werte aus den Registern zu laden.

Für den Zweck dieser Diskussion ist es die erste Aufgabe, über die Sie nachdenken müssen. Wenn Sie viele Anweisungen dekodieren müssen, um zu ermitteln, ob Werte aus den Registern benötigt werden, verlängert sich die Verzögerung, bevor Sie mit dem Lesen der Register beginnen können. Dies erhöht auch die Komplexität der ID-Stufe. Indem Sie einen einzigen Operationscode für alle Anweisungen vom Typ R reservieren, reduzieren Sie die Komplexität auf ein Minimum.

Es scheint ein wenig seltsam, dass Sie fünf Bits nur für das Verschieben verwenden. Ich kann mir ein paar mögliche Erklärungen vorstellen. Zum einen wird das Routing vereinfacht (diese fünf Bits werden IMMER direkt in die Registerdatei eingespeist, diese fünf Bits werden IMMER in den Barrel-Shifter eingespeist, diese sechs Bits werden IMMER an die ALU weitergeleitet, um zu bestimmen, welche Funktion auszuführen ist).

Sie haben möglicherweise darüber nachgedacht, in Zukunft kombinierte Anweisungen zum Verschieben nach links und zum Hinzufügen einzuführen. Dies hätte vermutlich die Form:

$d = $s + ($t << shamt)

2s+1s

Heutzutage würden wir wahrscheinlich nicht zweimal über eine komplexere Dekodierungsphase nachdenken, zumal Register-Dateizugriffe in der Pipeline einer typischen superskalaren CPU eher später erfolgen. Viele moderne CPUs führen sogar eine grobe Befehlsdecodierung durch, wenn ein Befehl in den L1-Cache eingefügt wird . Sie verbreitern die I-Cache-Zeilen ein paar Bits, um die zusätzlichen Informationen zu speichern (dank Moore's Law müssen Sie viele Transistoren verschwenden), damit die "richtige" Befehlsdecodierung einfacher und schneller wird.

Ein Grund, warum sie das Opcode-Feld wahrscheinlich so klein wie möglich halten wollten, ist, dass es J-Typ-Befehle nicht übermäßig bestraft. Wie Sie wahrscheinlich wissen, verwenden Befehle vom Typ J eine pseudo-direkte Adressierung. Zum Wohle aller, die zu Hause mitspielen, erkläre ich es kurz.

Das Adressfeld eines Befehls vom J-Typ ist 26 Bit. Da Befehle immer 4-Byte-ausgerichtet sind, müssen Sie nicht die niedrigstwertigen zwei Bits speichern, was bedeutet, dass Sie effektiv 28 Adressbits haben. Der Adressraum in MIPS I beträgt jedoch 32 Bit. Die oberen vier Bits der Sprungstelle werden also vom Programmzähler übernommen.

Dies bedeutet, dass Sie nicht direkt zu einem Ort springen können, an dem sich die vier höchstwertigen Bits des PC-Standorts unterscheiden. Sie müssten stattdessen einen teureren Drei-Anweisungen-Sprung durch ein Scratch-Register durchführen:

lui $r,target >> 16
    ori $r,$r,target & 0xFFFF
    jr $r

Das ist heute nicht schlecht, aber 1985 sind es viele Taktzyklen.

Wenn Sie ein wenig aus dem Adressfeld stehlen, würde sich die effektive Reichweite eines Direktsprungs noch weiter verringern. Sie können sehen, dass dieser Preis möglicherweise zu hoch ist.

Pseudonym
quelle
"kombinierte Anweisungen zum Verschieben nach links und Hinzufügen" des Typs, der später in ARM zu sehen ist?
Damian Yerrick