| Inhaltsverzeichnis | |||||
| Übersicht Kapitel 2 | |||||
| |||||
2.6.1 Registertypen |
Unter einem Register versteht man eine Speicherzelle mit minimaler Zugriffszeit, die ihren Inhalt ohne große Verzögerung zur Verfügung stellt. Dies wird einerseits dadurch erreicht, daß die Register meist auf dem Chip untergebracht sind. Dadurch entfällt das zeitraubende Umschalten der externen Adreß- und Datenwege. Andererseits kann wegen der relativ kleinen Anzahl von Registern ihre Auswahl durch individuelle Steuerleitungen geschehen, wodurch wiederum die Zeit der Adreßdecodierung entfällt. Die Menge der Register eines Prozessors wird als Registersatz (Register Set) bezeichnet.
Durch die Verwendung getrennter Ein- und Ausgänge können die Register zwischen zwei verschiedene interne Busse (Eingangsbus, Ergebnisbus) des Prozessors gehängt werden. Dies verkürzt wiederum die Zugriffszeit und erlaubt das Schreiben eines Registers gleichzeitig zum Lesen eines zweiten Registers. Insbesondere ist dadurch die Übertragung eines Registerinhaltes in ein anderes Register in einem Taktzyklus möglich.
Größere Registersätze müssen hingegen als Schreib-/Lesespeicher mit zusätzlichem Adreßdecoder realisiert werden, der zur eindeutigen Auswahl eines Registers dient. In diesem Fall spricht man auch von einem Registerspeicher oder Registerblock (Register File). In der einfachen Form kann zu jedem Zeitpunkt höchstens ein Register selektiert werden. Hier benötigt der angesprochene Registertransfer wenigstens zwei Taktzyklen und ein Hilfsregister zum Zwischenspeichern des transferierten Registerinhaltes. Bei den zum Abschluß dieses Abschnitts beschriebenen Multiport-Registersätzen sind die Adreßdecoder mehrfach ausgelegt, so daß "gleichzeitig", d.h. in einem Zyklus, mehr als ein Register zum Schreiben oder Lesen selektiert werden kann.
Oft besitzen einige der Register spezielle Funktionen, die durch Steuerleitungen aktiviert werden. Dazu gehören z.B. das Rücksetzen auf den Wert 0, das Inkrementieren bzw. Dekrementieren um 1 oder das Verschieben des Inhalts um ein Bit vorwärts, d.h. zu höheren Wertigkeiten, oder rückwärts.
| Selbsttestaufgabe S2.6-1: (–>Lösungsvorschlag) |
|---|
|
Skizzieren Sie den Aufbau eines universellen Registers, das alle erwähnten Funktionen ausführen kann: Rücksetzen, Vorwärts/Rückwärts-Schieben, Vorwärts/Rückwärts-Zählen. |
Bild 2.6-1 zeigt den typischen Registersatz eines Mikroprozessors. Die Register können unterschieden werden in Datenregister, Adreßregister und Spezialregister.

Bild 2.6-1: Registersatz eines Mikroprozessors
Datenregister
Die Datenregister (Data Register) dienen zur Zwischenspeicherung der Operanden bei allen arithmetischen und logischen Operationen. Zu ihnen gehören insbesondere die Akkumulatoren, die als "Sammelregister" für die ALU bei den meisten Operationen einen Eingabeoperanden und alle Ausgabeoperanden aufnehmen (vgl. Abschnitt 2.4.1). 16/32-bit-Mikroprozessoren besitzen meist keine spezialisierten Akkumula toren mehr, sondern statt dessen Datenregister, die alle in identischer Weise benutzt werden können. Die Breite der Datenregister stimmt in der Regel mit der Verarbeitungsbreite des Integer-Rechenwerks überein.
Die Adreßregister (Address Register) enthalten die Adressen oder Teile davon, die zur Auswahl eines Operanden oder eines Befehls im Speicher herangezogen werden. Dabei unterscheidet man noch weiter zwischen Basis- und Indexregistern (s. Bild 2.6-2). Diese Unterscheidung ist oft jedoch nur durch die Verwendung der Register in den Befehlen, nicht jedoch durch unterschiedliche Hardware erklärbar.

Bild 2.6-2: Zur Funktion von Basis- und Indexregister

Bild 2.6-3: Zur automatischen Modifikation von Indexregistern
Bei der ersten Variante (in Bild 2.6-3a) wird nach der Benutzung des Registerwertes dieser um den Wert n erhöht und in das Register eingetragen. Man spricht deshalb von einer Post-Inkrementierung. Bei der zweiten Variante (in Bild 2.6-3b) wird der Wert des Indexregisters vor der Adressierung einer Speicherzelle um n erniedrigt. Dieser erniedrigte Wert wird dann in das Register zurückgeschrieben. Man spricht hier von einer Pre-Dekrementierung. Die Größe n bestimmt den Anfang des nächsten adressierbaren Datums im Speicherbereich. Sie muß im Befehl angegeben werden. Für sie gilt typischerweise n=1, 2, 4, 8, je nach der Länge (in byte) der Daten im Speicherbereich.
Im Bild 2.6-3c ist ein Symbol für ein Register gezeichnet, das beide Modifikationen erlaubt. Vereinfachend spricht man von einem Autoinkrement/Autodekrement-Register. Natürlich ist es auch möglich, den Zeitpunkt der Inkrementierung bzw. Dekrementierung zu vertauschen, und so zu einer Pre-Inkrementierung bzw. Post-Dekrementierung zu kommen.
Im Bild 2.6-4 ist eine weitere, bei modernen 16/32-bit-Prozessoren gebräuchliche Methode skizziert, den Wert eines Indexregisters zu modifizieren. Sie wird Skalierung genannt. Bei ihr kann der Inhalt des Indexregisters vor der Auswertung mit einem skalaren Faktor n multipliziert werden. Für n sind, wiederum in Abhängigkeit von der aktuellen Länge der Daten (in byte), die Werte n=1, 2, 4, 8 üblich. In diesem Fall kann man sich zur Selektion des nächsten Datums darauf beschränken, den Registerinhalt jeweils nur um den Wert 1 zu inkrementieren bzw. zu dekrementieren. Die Länge des Registers wird dadurch effektiver genutzt.

Bild 2.6-4: Register mit Skalierung
Bei vielen 16/32-bit-Prozessoren, insbesondere den RISC-Prozessoren, wird nicht mehr zwischen den Daten- und Adreßregistern unterschieden. Dort spricht man dann von universellen Registern (General Purpose Register), die wahlweise als Adreß- oder Datenregister benutzt werden können.
Obwohl letztgenannte Register funktional zu anderen Komponenten des Prozessors, wie dem Adreßwerk, der Systembus-Schnittstelle oder dem Steuerwerk, gehören, werden sie der Vollständigkeit halber meist bei der Darstellung des Registersatzes mit aufgeführt.
Andere Spezialregister können durch Maschinenbefehle direkt adressiert werden. Dazu gehören z.B.:
2.6.2 Der Stack |
Der Stack (Kellerspeicher) ist ein besonderer Speicherbereich, der hauptsächlich zur Ablage des Prozessor-Status und des Programmzählers vor der Ausführung von Unterprogrammen oder Unterbrechungsroutinen dient, aber auch zur Übergabe von Parametern an diese Routinen und zur kurzzeitigen Lagerung von Daten als Zwischenergebnisse benutzt werden kann. Er ist normalerweise im Arbeitsspeicher angelegt (Software Stack). Einige der ersten Mikroprozessoren, aber auch neuere Entwicklungen und DSPs, besitzen jedoch auf dem Prozessorchip selbst einen Kellerspeicher (Hardware Stack) mit einer notwendigerweise sehr beschränkten Kapazität. Als Vorteil hat er jedoch eine erheblich kürzere Zugriffszeit als ein Software-Stack.
Moderne Prozessoren erlauben die gleichzeitige Verwaltung mehrerer getrennter Kellerspeicher im Arbeitsspeicher. Diese können z.B. einerseits dem Betriebssystem (System Stack), andererseits den Anwenderprogrammen (User Stack) oder ihren Daten (Data Stack) zugeordnet sein. Das Prinzip des Stacks besteht im wesentlichen darin, daß das zuletzt dort eingetragene Datum als erstes wieder gelesen und dabei aus ihm entfernt wird. Man spricht deshalb von einem Last-In-First-Out-Speicher (LIFO). Diese Verarbeitungsdisziplin erinnert an die übliche Behandlung eines Aktenstapels, so daß man auch den Ausdruck Stapelspeicher benutzt.
Das Stackregister (Stack Pointer - SP) enthält einen Zeiger
auf das zuletzt in den Stack eingetragene Datum. Im Vorgriff auf Abschnitt
3.2, sei hier schon erwähnt, daß es im Befehlssatz des Prozessors
spezielle Befehle zur Datenübertragung in den bzw. aus dem Stack gibt:
Durch den Befehl PUSH wird der Inhalt eines oder mehrerer Register in den Stack
übertragen, durch den Befehl PULL (manchmal auch mit POP bezeichnet) von
dort geladen. Bei jedem Zugriff zum Kellerspeicher über das Stackregister
wird dessen Inhalt in Abhängigkeit von der ausgeführten Operation
automatisch erhöht oder erniedrigt. Üblicherweise ist ein PUSH-Befehl
mit der Erniedrigung des Stackregisters verbunden, so daß der Stack "nach
unten wächst". Dabei sind für ein Befehlspaar PUSH/PULL beide
der bei den Indexregistern beschriebenen Möglichkeiten "predekrement/postinkrement"
oder "postdekrement/preinkrement" möglich. Im Bild
2.6-5 ist die erstgenannte Alternative der Verwaltung des Stackregisters
skizziert. Damit wollen wir die Beschreibung des Stacks beenden.

Bild 2.6-5: Verwaltung des Stackregisters
2.6.3 Registersätze realer Mikroprozessoren |
In diesem Abschnitt wollen wir in einigen Fallstudien die Registersätze wichtiger Mikroprozessor-Familien darstellen.
Fallstudie 2.6-1: Das Programmiermodell der x86-Prozessoren | ||||||
|
Bild 2.6-6: Der Registersatz der Intel-x86-Prozessoren Spezialregister Durch den 32-bit-Programmzähler (IP) können bis zu 232 Speicherzellen (4 Gbyte) physikalisch adressiert werden. Von den Flags des Statusregisters (Flag Register - EFR), die nicht bereits in diesem Abschnitt beschrieben wurden, sollen hier nur noch die Flags PF und DF erklärt werden. Auf die Erklärung der anderen muß aus Platzgründen verzichtet werden.
Die 16-bit-Segmentregister dienen der Verwaltung des Arbeitsspeichers. Hier soll nur erwähnt werden, daß sie die Nummern verschiedener Speicherabschnitte (Segmente) enthalten und vom Adreßwerk dazu benutzt werden, aus der in einem Befehl vorgegebenen logischen Adresse eine physikalische (Speicher-)Adresse zu berechnen. Die Segmentregister werden für jedes in Ausführung befindliche Programm mit individuellen Werten geladen. Die Segmente enthalten logisch unterscheidbare Teile des Programms, und zwar
Neben den bisher erklärten Registern besitzt der Prozessor noch eine Reihe weiterer spezieller Systemregister, die einerseits der Fehlersuche und dem Testen (Debug and Test) in Programmen, andererseits der Auftragsverwaltung in Multitasking-Betriebssystemen dienen, also solchen Betriebssystemen, die (quasi-)gleichzeitig verschiedene Programme ausführen können. Hier soll nur kurz auf das letzte im Bild 2.6-6 dargestellte Register eingegangen werden. Es trägt die Bezeichnung CR0 (Control Register 0) und wird häufig auch als Maschinenstatuswort MSW bezeichnet. In ihm werden die Zustandsflags gehalten, die sich nicht auf ein spezielles Programm (einen speziellen Auftrag) beziehen, sondern den Zustand des gesamten Systems beschreiben. (Diese Flags sollen hier nur erwähnt werden, ohne daß wir näher auf ihre Funktion eingehen können.)
Im Bild 2.6-7 sind die Register der Gleitpunkt-Einheiten (Floating-Point Unit - FPU) der x86-Prozessoren dargestellt.
Bild 2.6-7: Die Gleitpunkt/MMX-Register der x86-Prozessoren Jedes Floating-Point-Register besitzt 64 Bits für die Mantisse, 15 Bits für den positiven Exponenten und 1 Bit für das Mantissen-Vorzeichen. Die unteren 64 Bits der Register werden alternativ auch von der MMX-Einheit (Multimedia Extension, s. Abschnitt 2.4.3) mitbenutzt. Für die FPU existieren drei Spezialregister. Die Register der FPU werden in Form eines kleinen Hardware-Stacks verwaltet. Jede zweistellige Operation wirkt stets auf die beiden zuletzt eingeschriebenen Werte im Registersatz. Das Statusregister enthält dazu - neben den im Abschnitt 2.4.4 beschriebenen Statusflags - in zwei Bits TOP (Top of Stack) das "Stackregister", also den Zeiger auf den "jüngsten" Eintrag. Für jedes Datenregister enthält das Tag-Wort zwei Bits, in denen codiert abgelegt ist, ob das entsprechende Register leer ist oder der Eintrag eine gültige bzw. ungültige Zahl (NaN - Not a Number) oder die Zahl 0 enthält.Zu den dargestellten Registern der FPU kommt noch ein Speicher, das Konstanten-ROM, in dem einige Dutzend wichtige Gleitpunkt-Konstanten abgelegt sind (vgl. Abschnitt 2.4.3). |
Fallstudie 2.6-2: Das Programmiermodell der Motorola-680x0-Prozessoren |
|
Im Bild 2.6-8 ist der Teil des Registersatzes des Motorola MC680x0 dargestellt, der bei allen Mitgliedern der Familie realisiert ist. Darüber hinaus stimmt er weitgehend mit dem Registersatz der erfolgreichen Familie von 32-bit-Mikrocontrollern der Firma Motorola überein. Er entspricht sehr gut unserem allgemeinen Modell in
Bild 2.6-1.
Bild 2.6-8: Der Registersatz des Motorola MC680x0
Die beiden Cache-Register CACR (Cache Control Register) und CAAR (Cache Address Register, nur MC68020) steuern die Benutzung eines kleinen, schnellen Zwischenspeichers im Mikroprozessor, in dem wenige Maschinenbefehle gespeichert sind (Instruction Cache). (Auf sie und die Realisierung eines Cache-Speichers wird später ausführlich eingegangen.) Das Statusregister SR enthält neben den Zustandflags im CCR (Condition Code Register) sieben weitere Flags:
|
Fallstudie 6-9-3: Das Programmiermodell der PowerPC-Prozessoren |
|
Als drittes Beispiel wollen wir nun den Registersatz eines typischen RISC-Prozessors vorstellen. Dazu haben wir die PowerPC-Familie der Firmen Motorola und IBM ausgewählt. Wir beschränken uns dabei auf die Register, die dem Benutzer (im User Mode) zugänglich sind. Neben den dargestellten Registern besitzen die Mitglieder dieser Prozessorfamilie eine unterschiedliche große Anzahl von Registern, die nur im Betriebssystem-Modus (Supervisor Mode) angesprochen werden können und insbesondere der Ausnahmebehandlung und der Speicherverwaltung dienen.
Der Benutzer-Registersatz ist im Bild 2.6-9 dargestellt. Er besteht im wesentlichen aus zwei Registerspeichern (Register Files):
|
2.6.4 Registerspeicher |
Bereits zu Beginn der Mikroprozessor-Geschichte versuchte man, durch den Einsatz großer Registerspeicher auf dem Prozessor-Chip den hemmenden Einfluß zu verringern, der durch den Unterschied zwischen der (relativ hohen) Prozessorgeschwindigkeit und dem langsamen Hauptspeicher auftrat. So besaß bereits Mitte der 70er Jahre der F8-Prozessor der Firma Fairchild einen Registerblock aus 64 Registern (der Länge 8 bit), der als "Notizbuch-Speicher" (Scratchpad Registers) für die kurzzeitige Aufnahme häufig benutzter Daten (Operanden) und Adressen diente. Auch bei den Mikrocontrollern gibt es seit vielen Jahren Registerblöcke mit bis zu 256 Registern. Bei den seit Anfang der 80er Jahre auf dem Markt erscheinenden RISC-Prozessoren gehört ein großer Registerblock (mit wenigstens 32 Registern) zu den charakterisierenden Eigenschaften.
Dennoch ist auffällig, daß die Größe der implementierten Registerspeicher in keinem Verhältnis steht zu den bei modernen Mikroprozessoren auf dem Chip integrierten (Cache-)Speichern. Ein Grund liegt darin, daß ein großer Registerspeicher eine lange Adresse zur Selektion eines bestimmten Registers benötigt und diese Adresse im Befehlscode (OpCode) untergebracht werden muß.
Ein weiterer Grund, der die Komplexität großer Registerspeicher sehr stark anwachsen läßt, wird aus der bereits erwähnten Tatsache deutlich, daß in modernen Prozessoren nicht nur eine Komponente, sondern mehrere Komponenten gleichzeitig auf den Registerspeicher zugreifen müssen. Daher müssen die Registerblöcke als Multiport-Registerspeicher ausgelegt sein. Man findet heute Registerblöcke mit bis zu 16 Ein-/Ausgabeports. Da typische Rechenwerks-Operationen zwei Eingabeoperanden zu einem Ausgabeoperanden verarbeiten, sind meist mehr Ausgabeports als Eingabeports vorhanden. Im Bild 2.6-10 ist beispielhaft ein 4-Port-Registerspeicher skizziert.

Bild 2.6-10: Aufbau eines Multiportspeichers
Der Multiport-Registerspeicher erlaubt das gleichzeitige Auslesen und Einschreiben mehrerer Register. Dazu verfügt er über mehrfache Schnittstellen zu unterschiedlichen internen Bussen des Prozessors, die mit dem Begriff Port bezeichnet werden. Zur Selektion der beteiligten Register besitzt der Speicher einen vervielfältigten Adreßdecoder. Die technische Realisierung der Register, z.B. aus Master-Slave-Flipflops, erlaubt es sogar, im selben Taktzyklus dasselbe Register sowohl als Eingabe- wie auch als Ausgaberegister anzusprechen.
Über einen Ein-/Ausgabeport E/A (s. Bild 2.6-10) können die Register aus dem Hauptspeicher, einem internen (Cache-)Speicher oder einer Schnittstellenkomponente geladen bzw. ihre Inhalte dorthin ausgegeben werden. Über die beiden Ausgabeports A0, A1 werden zwei Registerinhalte als Operanden an die ALU übergeben. Das Ergebnis der ALU-Operation wird über den Eingabeport E in den Registerblock (zurück-)geschrieben (Write back).
Die im Bild 2.6-10 gezeigte Komponente Scoreboard ("Anzeigetafel") verhindert, daß Datenabhängigkeiten zwischen mehreren Operationen, die momentan ausgeführt werden, zu falschen Ergebnissen führen. Ein Register, das in einem in Ausführung befindlichen Befehl als Ergebnisregister selektiert wurde, wird z.B. im Scoreboard solange gekennzeichnet, bis das neue Ergebnis dort eingetragen wurde. Dadurch kann vermieden werden, daß nachfolgende Befehle vorzeitig auf den alten, ungültigen Registerwert zugreifen. Das Scoreboard ist im Bild vereinfacht als Bitvektor am Registerblock angehängt. Seine Realisierung benötigt in Realität eine aufwendige Schaltung mit umfangreichen Tabellen. Darauf wollen wir im Rahmen dieses Kurses jedoch nicht näher eingehen.
Wenn die ALU nach Bild 2.6-10 einen Operanden verarbeiten muß, der noch
nicht im Registerspeicher vorliegt, so muß dieser zunächst (über
den Port E/A) in einem Register abgelegt und kann frühestens einen Taktzyklus
später zur ALU weitergeleitet werden. Um diese Verzögerung zu vermeiden,
verfügen Registerspeicher häufig über einen Bypass
(" Umgehungsbus"), über den der Operand - gleichzeitig mit seiner
Ablage im Registerspeicher - auch an einen der Eingänge der ALU gelegt
werden kann. Diese Übertragung des Operanden wird als Load Forwarding
bezeichnet.
Eine ähnliche Situation tritt auf, wenn das Ergebnis einer ALU-Operation bereits in der folgenden Operation als Operand benötigt wird. In diesem Fall tritt eine Verzögerung (um wenigstens einen Taktzyklus) dadurch auf, daß das Ergebnis zunächst in den Registerspeicher (zurück-)geschrieben werden muß und erst im folgenden Takt von dort an einen ALU-Eingang gelegt werden kann. Auch zur Vermeidung dieser Verzögerung wird ein Bypass verwendet, der das Ergebnis unmittelbar an einen der ALU-Eingänge zurückkoppelt. So kann es gleichzeitig mit seiner Ablage im Registerblock bereits durch den folgenden Befehl verarbeitet werden. Diese Rückkopplung des Ergebnisses wird Result Forwarding genannt.
Zu den Registern, die durch die Maschinenbefehle eines Anwendungsprogramms angesprochen werden müssen, gehören neben den universellen Registern auch bestimmte Status- und Konstanten-Register. Die einfachste Art, eine große Anzahl von Registern zu verwalten, ist, sie als homogenen (unstrukturierten) Satz von Registern zu realisieren, die über eindeutige (absolute) Adressen selektiert werden. Auf die Probleme, die langen Registeradressen im Befehlscode unterzubringen, wurde bereits im Unterabschnitt 2.6.4.1 eingegangen. Ein weiterer Nachteil besteht darin, daß hardwaremäßig keinerlei Zuordnung von bestimmten Registern zu den aktiven Programmstrukturen (Hauptprogramme, Unterprogramme, Interruptroutinen usw.) vorgenommen werden kann.
Zur Vermeidung beider genannter Nachteile wurden Mechanismen zur strukturierten Verwaltung großer Registersätze entwickelt. Bei ihnen wird der gesamte Registerspeicher in mehrere Registerbänke unterteilt, die den o.g. Programmstrukturen dynamisch zugewiesen werden können. Dies ist im Bild 2.6-11 dargestellt.

Bild 2.6-11: Strukturierter Registerspeicher
Der Registerspeicher umfaßt (im unteren Adreßbereich) eine Registerbank, die die Konstanten-Register und alle globalen Register enthält, d.h. die Register, die für alle Programmstrukturen wichtig sind (z.B. das Statusregister). Die (restlichen) universellen Register sind in (n+1) gleich große, disjunkte Registerbänke unterteilt. Jeder der o.g. aktiven Programmstrukturen wird eine dieser Bänke (durch das Betriebssystem) zugewiesen, auf die sie exklusiv zugreifen darf. Durch diese Einteilung entsteht für jede Programmstruktur ein Registerfenster, das die "private" Registerbank und alle globalen und Konstanten-Register umfaßt. Die Adressierung eines privaten Registers im Registerfenster kann nun relativ geschehen: Beim Umschalten auf ein anderes Registerfenster wird die Anfangsadresse der zugehörigen Registerbank in ein spezielles Basisregister geladen. Im OpCode des Befehls muß nun lediglich eine kurze Registernummer angegeben werden, die als Index zum Basiswert addiert wird.
Ein Nachteil der beschriebenen Verwaltung des Registerspeichers tritt zu Tage, wenn z.B. von einem Unterprogramm Parameter an das aufrufende Hauptprogramm übergeben werden sollen, da diese (vom Betriebssystem) zeitaufwendig von einer Registerbank in eine andere kopiert werden müssen. In den folgenden Fallstudien werden Varianten der Verwaltung großer Registerspeicher gezeigt, die diesen Nachteil vermeiden. Die erste Variante benutzt überlappende Registerbänke einheitlicher Länge; die zweite hingegen läßt variable Längen von überlappenden oder disjunkten Bänken zu.
Fallstudie 2.6-4: Die Registerverwaltung der SPARC-Prozessoren |
|
Bild 2.6-12: Registerverwaltung der SPARC-Prozessoren Die Verwaltung der Registerbänke wird durch zwei Register vorgenommen: Das CWP-Register (Current Window Pointer) zeigt auf die Bank der momentan aktiven Programmstruktur. Beim Aufruf eines Unterprogramms wird der CWP auf den Beginn der nachfolgenden Bank gesetzt; beim Rücksprung aus dem Unterprogramm auf die Bank des aufrufenden Programms zurückgesetzt. Wie im Bild 2.6-12 angedeutet, ist die Folge der Registerbänke zyklisch geschlossen, d.h. von der Bank n wird auf die Bank 0 umgeschaltet (und umgekehrt).
Die unteren 8 Register jeder Bank werden als Eingabebereich (EPi), die oberen 8 als Ausgabebereich (APi) benutzt. Die mittleren 8 Register sind für das zugeteilte Programm als privater Bereich (PDi) reserviert. Jedes Programm (Haupt-, Unter-, Interruptprogramm) hat Zugriff auf ein Registerfenster, das wiederum aus der zugeteilten Registerbank und den globalen bzw. Konstanten-Registern besteht. Die Adressierung eines universellen Registers in der Registerbank geschieht auch hier durch die Angabe einer (relativen) Registernummer als Index, der zum (skalierten) CWP-Wert addiert wird. Durch die Überlappung der Bänke gestaltet sich jedoch die Parameterübergabe an ein aufrufendes oder aufgerufenes Programm effizienter: Das aufrufende Programm schreibt die Übergabeparameter in seinen Ausgabebereich. Nach dem Umschalten auf die Registerbank des Unterprogramms stehen sie (ohne zusätzlichen Transport) im Eingabebereich des Unterprogramms zur Verfügung. Das Unterprogramm seinerseits schreibt seine Ergebnisse in den eigenen Eingabebereich, wo sie nach dem Zurückschalten im Ausgabebereich des aufrufenden Programms zur Verarbeitung bereit stehen. |
Fallstudie 2.6-5: Die Registerverwaltung des Am29000 |
|
Bild 2.6-13: Registerverwaltung des Am29000 von AMD Der Registerspeicher unterstützt eine sehr flexible Adressierung und Auswahl der Register:
Beim Umschalten auf eine neue Programmstruktur (Hauptprogramm, Unterprogramm, Interruptroutine usw.) setzt das Betriebssystem den Stack Pointer auf einen neuen Basiswert. Dieser besteht aus der absoluten Adresse (Nummer) eines lokalen Registers. Auf ihn werden - wie oben beschrieben - die relativen Registeradressen (0,...,..) der Programmstruktur bezogen. Prinzipiell kann so der gesamte Bereich der lokalen Register ab der Basisadresse oder aber ein kleinerer Teil davon der Programmstruktur zugewiesen werden. Auf die beschriebene Weise entstehen Registerbänke mit unterschiedlichen Längen (vgl. Bild 2.6-14).
Bild 2.6-14: Registerfenster-Verwaltung beim Am29000 Das Betriebssystem kann den Wert des Stack Pointers, z.B. eines aufgerufenen Unterprogramms, in den Bereich des aufrufenden Programms setzen. Auf diese Weise überlappen sich die Registerbänke der Programmstrukturen. Es ist dadurch möglich, jede Registerbank (wie beim SPARC) in Eingabe-/Ausgabebereiche und private Datenbereiche zu strukturieren. Die aktive Programmstruktur hat Zugriff auf ein Registerfenster, wie es im Bild 2.6-14 rechts skizziert ist. Auf diese Fenster wird auf die beschriebenen Arten zugegriffen: auf alle globalen Register durch absolute Adressen (Nummern), auf die lokalen Register relativ, bezogen auf den Stack Pointer. (Zur Adressierung wird der Inhalt von Register 1, Stack Pointer genannt, zunächst in ein Spezialregister kopiert, das im Bild ebenfalls als Stack Pointer bezeichnet ist.) |
| Inhaltsverzeichnis | |||||
| Übersicht Kapitel 2 | |||||
| |||||