Kapitel 3 Der DLX als RISC-Beispiel
Kapitel 3 Der DLX als RISC-Beispiel
Kapitel 3 Der DLX als RISC-Beispiel
Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
120 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIEL• Datentransfer-Befehle• Arithmetisch-logische Befehle• Sprungbefehle• GleitkommabefehleDie einzelnen Befehlsgruppen werden in den folgenden Abschnitten genauer beschrieben.Ein vollständige Liste aller Befehle ist in Abschnitt 3.1.5 angegeben.3.1.1 Datentransfer-BefehleSpeicherzugriffeDie Load und Store-Befehle des <strong>DLX</strong> unterstützen genau eine Adressierungsart,nämlich „Register-indirekt mit Displacement“. Die effektive Adresse ergibtsich aus der Summe eines Registerinhaltes mit einem konstanten Displacement.Implizit sind damit die Adressierungsarten „absolut“ und „Register-indirekt“ eingeschlossen:für die absolute Adressierung wird <strong>als</strong> Register R0 gewählt, für dieRegister-indirekte Adressierung wird ein Displacement von 0 eingesetzt.Oben wurde gesagt, dass der <strong>DLX</strong> Integerzahlen mit unterschiedlicher Wortbreite(8, 16, 32 Bit) bearbeiten kann. Tatsächlich wird intern stets mit 32 Bit gerechnet,und Zahlen geringerer Wortbreite werden beim Laden vorzeichenrichtigerweitert und konvertiert. Dementsprechend gibt es die folgenden Varianten desLoad-Befehls:• LBU („load byte unsigned“): ein Byte (8 Bit) wird gelesen und die oberen24 Bit des Zielregisters werden auf 0 gesetzt.• LB („load byte“): ein Byte (8 Bit) wird gelesen und das Vorzeichenbit (Bit7) wird in die oberen 24 Bit des Zielregisters kopiert.• LHU („load halfword unsigned“): wie LBU, allerdings wird ein 16-Bit-(Halb-) Wort gelesen.• LH („load halfword“): wie LB, allerdings wird ein 16-Bit-(Halb-)Wort gelesen.• LW („load word“): liest ein 32-Bit Wort.• LF („load float“): liest einen Gleitkommawert mit einfacher Genauigkeit.Date: 2002/10/18 16:21:27 Revision: 1.96
122 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELByte0 1 2 3 4 5 6 7HalbwortWortAbbildung 3.1: Ausgerichtete Speicherzugriffe• zum Transfer zwischen zwei Integer-Registern und• zum Laden irgend eines Registers mit einer Konstanten.Für die beiden letzten Fälle können (bzw. müssen) äquivalente arithmetische Befehleverwendet werden (s. u.).3.1.2 Arithmetisch-logische BefehleBeim <strong>DLX</strong> wird ein 3-Adress-Konzept verfolgt, d. h. jeder ALU-Befehl besitzteinen Ziel und zwei Quelloperanden. <strong>Der</strong> Ziel und der erste Quelloperand sinddabei stets Register, der zweite Quelloperand kann ein Register oder ein 16-BitDirektwert sein.Die unterstützten Operationen lassen sich wie folgt gruppieren:• arithmetische Operationen: ADD, SUB, MULT, DIV• logische Verknüpfungen: AND, OR, ...• Schiebeoperationen (rechts/links, arithmetisch/logisch): SRL, SRA, SLL, ...• Vergleichsoperationen, z. B.: SLT („set less than“)Bei den Befehlen MULT und DIV gibt es eine Besonderheit: Um Hardware zusparen, werden der Multiplizierer und der Dividierer in der Gleitkommaeinheitauch für Integer-Operationen verwendet. Die Konsequenz für den ProgrammiererDate: 2002/10/18 16:21:27 Revision: 1.96
3.1. BEFEHLSSATZ 123ist, dass die Operanden von MULT und DIV Gleitkommaregister (F0...F31) seinmüssen, deren Inhalte jedoch <strong>als</strong> Integerzahlen interpretiert werden.Mit Schiebebefehlen ist es möglich, Registerinhalte um eine beliebige Anzahlvon Bitstellen nach links bzw. rechts zu verschieben. Man unterscheidet zwischenarithmetischem und logischem Schieben. Beim logischen Schieben werden diehereingeschobenen Stellen stets mit 0 aufgefüllt, beim arithmetischen Schiebennach rechts werden sie mit dem Vorzeichenbit aufgefüllt. Arithmetisch betrachtetbedeutet das Schieben um eine Stelle nach rechts die „Halbierung” des Wertes(genauer: SRA x = x div 2). Beim SRA-Befehl („shift right arithmetically“)bleibt diese Eigenschaft auch für Zweierkomplementzahlen bestehen. Die Zahl11110110 2 hat z. B. den Wert -10. Arithmetisch nach rechts geschoben ergibt sich11111011 2 = -5, schiebt man logisch, so erhält man 01111011 2 = 123.Zur Unterstützung von bedingten Sprüngen gibt es mehrere Operationen mit Namender Form „Sxx“. SGT („set greater than“) vergleicht z. B. die beiden Quelloperandenund schreibt in das Zielregister eine 1, falls die Bedingung wahr ist,d. h. der erste Quelloperand größer <strong>als</strong> der zweite ist. Andernfalls wird in dasZielregister der Wert 0 geschrieben.ALU-Befehle können dazu genutzt werden, Daten zwischen Integerregistern zuverschieben bzw. Integerregister mit einem Direktwert zu laden. <strong>Der</strong> BefehlADD R1, R0, R2kopiert z. B. den Inhalt von R2 nach R1 und der BefehlADD R1, R0, # 5lädt R1 mit der Konstanten 5.Das Laden von 32-Bit-Konstanten ist mit dem Befehl LHI („load high immediate“)möglich. Er lädt eine 16-Bit-Konstante in die oberen 16 Bit des Zielregistersund löscht die unteren 16 Bit. So ist es möglich, mit zwei aufeinanderfolgendenBefehlen der FormLHIR1, # ADD R1, R1, # eine beliebige 32-Bit-Konstante in ein Register zu laden.Tabelle 3.2 zeigt einige <strong>Beispiel</strong>e für arithmetische und logische Befehle.<strong>Beispiel</strong>eSeien a, b, c, d Integer-Zahlen (32-Bit). Dieses kurze Programm berechnet dieSumme der Zahlen a, b und c. Das Ergebnis wird in d gespeichert (ohne Berück-Date: 2002/10/18 16:21:27 Revision: 1.96
124 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELBefehl Name BedeutungADD R1,R2,R3 Add Regs[R1]←Regs[R2]+Regs[R3]ADD R1,R2,# 3 Add Regs[R1]←Regs[R2]+3OR R1,R2,R3 Or Regs[R1]←Regs[R2] ∨ Regs[R3]SLL R1,R2, # 5 Shift left logical Regs[R1]←Regs[R2]<
3.1. BEFEHLSSATZ 125oder 0 ist. Meist werden sie zusammen mit den Sxx-Befehlen (s. o.) verwendet.Tabelle 3.3 zeigt einige <strong>Beispiel</strong>e für Sprungbefehle. Bei allen direkten Sprüngenwird die Zieladresse durch einen relativen Offset zum Befehlszäher mit einerWortbreite 16-Bit oder 26-Bit kodiert. Dadurch sind direkte Sprünge außerhalbeines Radius von ±2 15 bzw. ±2 25 nicht möglich. Für Sprünge außerhalb diesesRadius bzw. für absolute Sprünge muss ein indirekter Sprungbefehl (JR) verwendetwerden.Befehl Name BedeutungJ name Jump PC←Name;((PC+4)-2 25 ) ≤ name < ((PC+4)+2 25 )JAL name Jump and link R31←PC+4; PC←Name;JR R3 Jump register PC←Regs[R3]((PC+4)-2 25 ) ≤ name < ((PC+4)+2 25 )BEQZ R4, name Branch equal zero if (Regs[R4]==0) PC←Name;((PC+4)-2 15 ) ≤ name < ((PC+4)+2 15 )Tabelle 3.3: <strong>Beispiel</strong>e für SprungbefehleMit dem Befehl JAL können Unterprogramme realisiert werden. JAL springt undkopiert vorher den aktuellen Befehlszählerinhalt in das Register R31. <strong>Der</strong> Rücksprungaus dem Unterprogramm geschieht mit dem Befehl „JR R31“. Diese Technikist schneller <strong>als</strong> die CALL/RET-Befehle anderer Prozessoren (z. B. Intel x86,Motorola 68xxx), die die Rücksprungadresse auf einem Stack speichern/lesen,denn es sind keine Speicherzugriffe nötig. Andererseits sind mit JAL/JR R31 keinegeschachtelten oder gar rekursiven Aufrufe möglich. Hierzu muss beim <strong>DLX</strong>softwaremäßig ein Stack implementiert werden.Delayed BranchingBei der Programmierung des <strong>DLX</strong> ist zu beachten, dass der unmittelbar auf einenSprungbefehl folgende Befehl stets ausgeführt wird („delayed branching“), <strong>als</strong>würde er vor dem Sprungbefehl stehen.<strong>Der</strong> Grund hierfür ist, dass der <strong>DLX</strong> (wie die meisten modernen Prozessoren) eineBefehlspipeline besitzt. Die Ausführung eines Befehls erfolgt in mehreren (beim<strong>DLX</strong> 5) Phasen, die alle mindestens einen Taktzyklus benötigen. <strong>Der</strong> Durchsatzbeträgt ohne Pipelining damit höchstens 1 Befehl / 5 Takte. Mit etwas Zusatzhardwareist es jedoch möglich, verschiedene Phasen für verschiedene Befehle parallelDate: 2002/10/18 16:21:27 Revision: 1.96
126 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELauszuführen, so dass in jedem Takt ein neuer Befehl gestartet wird (s. Abbildung3.2). Damit ist ein Durchsatz von einem Befehl pro Takt möglich.Bei einem Sprungbefehl steht jedoch erst in einer relativ späten Phase die Sprungadresse(und bei bedingten Sprüngen, ob überhaupt gesprungen wird) fest. EinigeBefehle, die im Programmtext auf den Sprungbefehl folgen, sind damit schon teilweiseausgeführt worden.Ohne PipeliningTaktz.B. 1 2 3 4 5 6 7 8ADDBNEZLW1 2 3 4 5Mit Pipelining1 2 3 4 5z.B. 1 2 3 4 5 6 7 8ADDBNEZLWTakt1 2 3 4 51 2 3 4 51 2 3 4 5Abbildung 3.2: Prinzip des PipeliningFür das Problem gibt es prinzipiell zwei Lösungswege:9 10• Hardware-basiert: Wird ein Sprungbefehl erkannt, so wird die Pipeline gelöscht.Dies ist mit einem Zeitverlust verbunden.• Software-basiert: Von Seiten der Hardware wird nichts unternommen undman überlässt es dem Compiler bzw. Programmierer, lauffähigen Code zuerzeugen. Man definiert einen sog. Branch-Delay-Slot, d. h. eine Anzahlvon Befehlen, um die ein Sprung scheinbar verzögert ausgeführt wird (beidem Simulator „dlxsim“ beträgt der Delay-Slot einen Befehl).In der Praxis erweist sich bei der Assemblerprogrammierung das „delayed branching“<strong>als</strong> beliebte Fehlerquelle. Um Verwirrung zu vermeiden, folgt in den meisten<strong>Beispiel</strong>programmen dieses Skriptes daher auf jeden Sprungbefehl ein „NOP“.Dem Leser sei beim Lösen der Übungsaufgaben wärmstens empfohlen, sich ebenfallsanzugewöhnen, NOP-Befehle einzufügen.Date: 2002/10/18 16:21:27 Revision: 1.96
3.1. BEFEHLSSATZ 127<strong>Der</strong> Vorteil des „delayed branching“ besteht darin, dass gut optimierende Compilerdie Delay-Slots mit sinnvollen Befehlen füllen können und so sehr schnellenausführbaren Code erzeugen.<strong>Beispiel</strong>e1. Das kurze Programmfragmentif (R1>R2) then R3:=5;entspricht folgendem <strong>DLX</strong>-Assemblercode:SGT R10, R1, R2 ; Vergleiche R1, R2BEQZ R10, cont ; Sprung, wenn R1 = R2 and R1 < R3) then R4 := 5;sind im <strong>DLX</strong>-Assemblercode zwei Alternativen möglich:ALTERNATIVE A:SGE R10, R1, R2 ; R1≥R2 ?SLT R11, R1, R3 ; R1
128 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELSGE R10, R1, R2 ; R1≥R2 ?BEQZ R10, cont ; Sprung, falls NEINNOPSLT R10, R1, R3 ; R1 R1 = 8, R2 = 4...5. Für die Verwaltung von lokalen Variablen und Parametern in Aktivierungsblöcken(s. <strong>Kapitel</strong> 2.2 über Befehlssätze) erzeugt ein Compiler sogenanntenProzedur-Eintritts- und Austrittscode. Abbildung 3.3 zeigt ein Pascal-Programmfragment und den konkreten Aufbau des Aktivierungsblocks derProzedur A.Für die Verwaltung des Aktivierungsblocks reserviert der Compiler einige Prozessor-Date: 2002/10/18 16:21:27 Revision: 1.96
3.1. BEFEHLSSATZ 129procedure Main;var i,j,k: integer; r: real;procedure A (x: integer);var j,l,m: integer;begin...end;begin...end;SP´-28SP´-16SP´-12SP´-8SP´-4jlm← PPDynamischer ZeigerStatischer ZeigerRücksprungadressexVorhergehenderAktivierungsblock← SP← SP´Abbildung 3.3: Programm-<strong>Beispiel</strong> und zugehöriger AktivierungsblockRegister, z. B.:r20r21r22- Stackpointer- aktueller dynamischer Zeiger (FP), Zugriff auf x, j, l, m- aktueller statischer Zeiger, Zugriff auf i, j, k, r<strong>Der</strong> Eintritts und Austrittscode für die Prozedur A in Abbildung 3.3 könnte dannlauten:procA: sw -8(r20), r31 ; Rücksprungadresse speichernsw -12(r20), r22 ; statischen Zeiger speichernsw -16(r20), r21 ; dynamischen Zeiger (alten FP) speichernsub r21, r20, #16 ; FP setzen - in Abbildung 3.3 mit PP gekennzeichnetsub r20, r20, #28 ; SP setzen, Platz für lokale Variablen schaffen.... ; Rumpf der Prozeduradd r20, r20, #28 ; SP restaurierenlw r21, -16(r20) ; dynamischen Zeiger restaurierenlw r22, -12(r20) ; statischen Zeiger restaurierenlw r31, -8(r20) ; Rücksprungadresse lesenjr r31 ; Rücksprungnop3.1.4 Gleitkomma-BefehleDie Gleitkomma-Einheit des <strong>DLX</strong> beherrscht die vier Grundrechenarten und bearbeitetwahlweise Daten einfacher (32-Bit) oder doppelter (64-Bit) Genauigkeit.Date: 2002/10/18 16:21:27 Revision: 1.96
130 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELFür Rechnungen mit doppelter Genauigkeit werden die Gleitkommaregister paarweisezusammengefasst. <strong>Der</strong> Befehlmultf f0, f1, f2multipliziert z. B. die Inhalte der Register F1 und F2 mit einfacher Genauigkeitund schreibt das Ergebnis in das Register F0. <strong>Der</strong> Befehlmultd f0, f2, f4multipliziert die Inhalte der Registerpaare F2/F3 und F4/F5 mit doppelter Genauigkeitund legt das Ergebnis in dem Registerpaar F0/F1 ab.In Abschnitt 3.1.1 wurden bereits MOV-Befehle zum Transfer zwischen Gleitkommaund Integer-Registern angesprochen. Diese Befehle kopieren ein Datenwortbitweise und es wird keinerlei Konvertierung vorgenommen. Um zwischenverschiedenen Zahlendarstellungen zu konvertieren gibt es Befehle der Form CV-Tx2y, wobei x und y stehen können für:• I - Integerzahl• F - Gleitkommazahl mit einfacher Genauigkeit• D - Gleitkommazahl mit doppelter GenauigkeitAnalog zu den Sxx-Befehlen gibt es Vergleichsbefehle für Gleitkommazahlen(z. B. LTx, GTx, EQx mit x∈{ F, D }). <strong>Der</strong> Befehlltf f0, f1prüft z. B., ob F0 < F1 ist und speichert das Ergebnis in einem Flag, das von denbedingten Sprungbefehlen BFPT („branch on floating point true“) oder BFPF („...f<strong>als</strong>e“) abgefragt werden kann.<strong>Beispiel</strong>Das folgende Programmfragment berechnet den Wert des Bruchs 13/7:add r1, r0, # 13 ; R1 mit 13 ladenmovi2fp f1, r1 ; R1 nach F1 kopierencvti2f f2, f1 ; F1 in float wandeln => F2add r1, r0, # 7 ; R1 mit 7 ladenmovi2fp f1, r1 ; R1 nach F1 kopierencvti2f f3, f1 ; F1 in float wandeln => F3divf f1, f2, f3 ; Division durchführen; Ergebnis steht in F1Date: 2002/10/18 16:21:27 Revision: 1.96
3.2. <strong>DLX</strong>-ASSEMBLER UND -SIMULATOR 131Um die Division durchführen zu können müssen die Operanden in FP-Registernstehen. <strong>Der</strong> Befehl CVTI2F (Convert Integer to Float) erwartet allerdings zweiFP Register, <strong>als</strong>o müssen die Integer-Zahlen erst in die FP-Register kopiert (mittelsMOVI2FP) und danach konvertiert werden. Erst jetzt ist die Division korrektdurchführbar.3.1.5 Zusammenfassung des <strong>DLX</strong>-BefehlssatzesIn Tabelle 3.4 - Tabelle 3.7 ist eine vollständige Übersicht aller <strong>DLX</strong>-Befehledargestellt. Dabei steht Rx/Ry/Rz für Integer-Register, Fx/Fy/Fz für Fließkomma-Register, n für eine natürliche Zahl und # n für eine Konstante.Befehl Bedeutung BemerkungLB Rx, Ry(n) Load byteLBU Rx, Ry(n) Load byte unsigned 8 BitSB Rx, Ry(n) Store byteLH Rx, Ry(n) Load half wordLHU Rx, Ry(n) Load half word unsigned 16 BitSH Rx, Ry(n) Store half word unsignedLW Rx, Ry(n) Load wordSW Rx, Ry(n) Store word 32 BitLF Fx, Ry(n) Load floatLD Fx, Ry(n) Load double lädt Fx und F(x+1)SF Fx, Ry(n) Store SP floatSD Fx, Ry(n) Store DP floatMOVI2SMove from integer register to a specialregisterMOVS2IMove from a special register to integerregisterMOVF Fx, Fy Move floatMOVD Fx, Fy Move DPMOVFP2I Rx, Fy Move float to integerMOVI2FP Fx, Ry Move integer to floatTabelle 3.4: Datentransfer-Befehle3.2 <strong>DLX</strong>-Assembler und -SimulatorFür die praktischen Übungsaufgaben über den <strong>DLX</strong> ist auf den Rechnern der AbteilungRechnerarchitektur ein <strong>DLX</strong>-Simulator mit integriertem Assembler „<strong>DLX</strong>sim“installiert.Date: 2002/10/18 16:21:27 Revision: 1.96
132 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELBefehl Bedeutung BemerkungADD Rx, Ry, Rz/# n AddSUB Rx, Ry, Rz/# n SubtractMULT Fx, Fy, Fz MultiplyMULTU Fx, Fy, Fz Multiply unsignedDIV Fx, Fy, Fz DivideDIVU Fx, Fy, Fz Divide unsignedAND Rx, Ry, Rz/# n AndOR Rx, Ry, Rz/# n OrXOR Rx, Ry, Rz/# n exclusive orLHI Rx, # n Load high immediateSLL Rx, Ry, Rz/# n Shift left logicalSRL Rx, Ry, Rz/# n Shift right logicalSRA Rx, Ry, Rz/# n Shift right arithmeticSLT Rx, Ry, Rz/# n Set less thanSGT Rx, Ry, Rz/# n Set greater thanSLE Rx, Ry, Rz/# n Set less or equalSGE Rx, Ry, Rz/# n set greater or equalSEQ Rx, Ry, Rz/# n Set EqualSNE Rx, Ry, Rz/# n Set not EqualTabelle 3.5: Arithmetisch-logische BefehleBefehl Bedeutung BemerkungBEQZ Rx, label Branch on General Purpose Register(GPR) equal zeroBNEZ Rx, label Branch on GPR not equal zeroBFPT label Branch on floating point trueBFPF label Branch on floating point f<strong>als</strong>eJ label JumpJR Rx Jump registerJAL label Jump and linkJALR Rx Jump and link registerTRAP # n Trap löst Software- InterruptausRFE Return from exception Rückkehr von Softw.-InterruptTabelle 3.6: SprungbefehleDate: 2002/10/18 16:21:27 Revision: 1.96
3.2. <strong>DLX</strong>-ASSEMBLER UND -SIMULATOR 133Befehl Name BedeutungADDD Fx, Fy, Fz Add doubleADDF Fx, Fy, Fz Add floatSUBD Fx, Fy, Fz Subtract doubleSUBF Fx, Fy, Fz Subtract floatMULTD Fx, Fy, Fz Multiply doubleMULTF Fx, Fy, Fz Multiply floating pointDIVD Fx, Fy, Fz Divide doubleDIVF Fx, Fy, Fz Divide floating pointCVTF2D Fx, Fy Convert float to doubleCVTF2I Fx, Fy Convert float to integerCVTD2F Fx, Fy Convert double to floatCVTD2I Fx, Fy Convert double to integerCVTI2F Fx, Fy Convert integer to floatCVTI2D Fx, Fy Convert integer to doubleLTD Fx, Fy Less than (double)GTD Fx, Fy Greater than (double)GED Fx, Fy Greater or equal (double)EQD Fx, Fy Equal (double)NED Fx, Fy Not equal (double)LTF Fx, Fy Less than (float)GTF Fx, Fy Greater than (float)GEF Fx, Fy Greater or equal (float)EQF Fx, Fy Equal (float)NEF Fx, Fy Not equal (float)Tabelle 3.7: Gleitkomma-BefehleDate: 2002/10/18 16:21:27 Revision: 1.96
134 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELEine vollständige Anleitung zu <strong>DLX</strong>sim („<strong>DLX</strong>sim - Simulator and Debuggerfor <strong>DLX</strong> assembly programs“) wird separat ausgegeben. Eine Einführung in dieBedienung mit erläuternden <strong>Beispiel</strong>en wird in den folgenden beiden Abschnittengegeben.3.2.1 AssemblerEin Assembler übersetzt ein Maschinenprogramm in textueller Darstellung in einebinäre Form, die vom Prozessor gelesen und ausgeführt werden kann (s. Abbildung3.4). Eine Assembler-Datei kann mit einem beliebigen Texteditor (z. B.‘emacs’ oder ‘vi’) erstellt werden..data 0x100size: .word 4 0x0100: 0x00000004array: .word 3, 17, 19, 2 0x0104: 0x000000030x0108: 0x000000110x010c: 0x000000130x0110: 0x00000002.text 0x200start: lw r1, size 0x0200: 0x8c010100sub r1, r1, #1 0x0204: 0x28210001sll r1, r1, #2 0x0208: 0x50210002lw r2, array (r1) 0x020c: 0x8c220104loop: sub r1, r1, #4 0x0210: 0x28210004lw r3, array (r1) 0x0214: 0x8c230104slt r4, r2, r3 0x0218: 0x0043202abeqz r4, cont 0x021c: 0x10800008nop 0x0220: 0x00000000add r2, r0, r3 0x0224: 0x00031020cont: bneznopr1, loop 0x0228:0x022c:0x1420ffe40x00000000trap #0 0x0230: 0x44000000Abbildung 3.4: Assemblerprogramm und zugehöriger MaschinencodeBefehle und Operanden werden genauso geschrieben, wie sie in <strong>Kapitel</strong> 2.2 eingeführtwurden. Konstanten sollten, müssen aber nicht mit einem führenden ‘#’-Zeichen eingegeben werden.Zur Eingabe von Daten und um anzugeben, wie das Programm und die Daten indem <strong>DLX</strong>-Speicher abgelegt werden sollen, gibt es eine Reihe von Assembler-Direktiven, die anstelle von <strong>DLX</strong>-Befehlen in der Assembler-Datei auftreten können.Die wichtigsten Direktiven sind:.text :.data :.byte / .word / .ascii / .float/ .double .space :Gibt die Anfangsadresse des Programmes an.Gibt die Anfangsadresse für Daten an.Fügt Daten in verschiedenen Formaten in den Datenbereich einreserviert Bytes im Datenbereich.Date: 2002/10/18 16:21:27 Revision: 1.96
3.2. <strong>DLX</strong>-ASSEMBLER UND -SIMULATOR 135Einige <strong>Beispiel</strong>e für Assembler-Direktiven sind:.text 0x100 ; alle Befehle werden ab 100 16 abgelegt.data 0x200 ; alle Daten werden ab 200 16 abgelegt.byte 15, 63, 255.double 1.2, 3.1415926535.space 1024 1024 ; Bytes freihaltenEine weitere Direktive ist .macro und .endmacro. Da diese Direktiven von dlxsimnicht unterstützt werden haben sie für die Rechnerübungen keine praktischeBedeutung. Die Funktionsweise ist im folgenden Programmausschnitt dargestellt:.macro djnz (reg,label)sub reg, reg, #1bnez reg, labelnop.endmacro...djnz r4, loop → sub r4, r4, #1bnez r4, loopnopUm dem Programmierer die Eingabe von absoluten oder relativen Adressen beiDatenzugriffen und Sprüngen zu erleichtern, können Labels verwendet werden.Ein Label ist eine Folge von Buchstaben, Ziffern und den Zeichen ‘_’ und ‘$ ’,wobei das erste Zeichen keine Ziffer sein darf. Ein Ausdruck der Form: ordnet dem Label die Adresse des/der hinter dem Doppelpunkt stehenden Befehls/Direktivezu. Auf diese Adresse kann später unter Verwendung des Labelnamens zugegriffen werden.Abbildung 3.5 zeigt, wie der Assembler Labels in absolute oder relative Adressenumsetzt.Kommentare in Assemblerdateien beginnen mit einem ‘;’ und enden mit dem Zeilenende.Arithmetische Ausdrücke, welche von dem <strong>DLX</strong>-Assembler unterstützt werden,sind Konstanten, die mit Operatoren verknüpft werden können.Konstanten können sein:• Dezimalzahlen, z. B. 3, -7, 0, ...• Hexadezimalzahlen, z. B. 0x3e, 0xffff, ...Date: 2002/10/18 16:21:27 Revision: 1.96
136 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELa) absolute Adressierung.data 0x100size: .word 4array:.word 3, 17, 19, 2...⇒ size = 0x0100⇒ array = 0x0104lwb) relative Adressierungr2, array (r1) → lw r2, 0x0104(r1)→ 0x8x220104(0x0210) loop: sub r1, r1, #4...(0x0228) bnez r1, loop 0x1420ffe4(0x022c)loop = 0x02100x0210 - 0x022c = -0x1cim 2er-Komplement (16 Bit):0xffe4Abbildung 3.5: Auflösung von Labels• LabelsNegative Zahlen werden automatisch ins 2er-Komplement gewandelt, und Gleitkommazahlenwerden nach dem IEEE-Standard kodiert.Operatoren können sein:• Grundrechenarten: +, -, *, /, % (modulo)• logische Op.: & (und), | (oder), ˆ (xor)• Schieben: < >• Klammerung: (, )Einige <strong>Beispiel</strong>e zu arithmetischen Ausdrücken sind in Abbildung 3.6 dargestellt.Achtung: Alle Ausdrücke werden beim Assemblieren aufgelöst und dürfen nurKonstanten bzw. Labels enthalten! Nicht erlaubt ist z. B.:add r1, r2, r3 & 7Date: 2002/10/18 16:21:27 Revision: 1.96
3.2. <strong>DLX</strong>-ASSEMBLER UND -SIMULATOR 137– B eispiele:.data0x100first: .word 1,2,3,4,5,6last: .word 7...add r1, r0, (last-first) / 4 + 1lhi r4, 1000000 >> 16= 0xf= 7add r4, r4, 1000000 % 65536= 0x4240(f4240 16 = 1000000 10 )A ch tu ng !A lle Ausdrücke werden beim Assemblieren aufgelöstund dürfen nur Konstanten bzw. Labels enthalten!F a lsc hadd r1, r2, r3 & 7R ichtigadd r1, r2, 7add r1, r2, r4Abbildung 3.6: <strong>Beispiel</strong>e zu arithmetischen AusdrückenDate: 2002/10/18 16:21:27 Revision: 1.96
138 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELLabelStart des Datenbereichs.data 0x0000a: .double 3.14159265358979x: .double 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16.double 17,18,19,20,21,22,23,24,25,26,27xtop: .double 28Start des Programmbereichs.text 0x0100LD F2,aADD R1,R0,xtop ; r1 mit der Adresse von “xtop” ladenloop: LD F0,0(R1)MULTD F4,F0,F2KommentarSD 0(R1),F4SUB R1,R1,#8 ; r1 um sizeof(double) erniedrigenBNEZ R1,loop ; Sprung, falls r1≠0NOP; “Delayed Branching”TRAP #0 ; SimulationsendeAbbildung 3.7: <strong>Beispiel</strong> für eine Assembler-DateiAbbildung 3.7 zeigt eine vollständige Assemblerdatei. Als Übung sollte der Leserversuchen, zu beschreiben, was das dargestellte Programm tut. Die Auflösungwird in Abschnitt 3.2.2 gegeben.<strong>Der</strong> Befehl „TRAP # 0“ am Programmende spielt bei <strong>DLX</strong>sim eine Sonderrolle: erweist den Simulator an, beim Erreichen dieses Befehls die Simulation zu beenden.3.2.2 Cross-SimulationDie meisten Leser werden sicherlich schon das eine oder andere Computerprogrammselbst geschrieben haben. Vermutlich sind diese Programme auf dem gleichenComputer entwickelt worden, auf dem sie laufen sollten. <strong>Der</strong> Entwicklungsflussist in Abbildung 3.8 dargestellt. Das geschriebene Programm wird mit einemAssembler oder Compiler (bei Hochsprachen) übersetzt. Es entsteht ausführbarerCode, den man einfach laufen lässt, um die Korrektheit und die Leistungsfähigkeitzu überprüfen.Es kann aber auch vorkommen, dass bei der Software-Entwicklung das Zielsystemüberhaupt nicht zur Verfügung steht. Ein Software-Hersteller, der seine Programmefür ein neues Rechnersystem oder eine neue Prozessorvariante auf den Marktbringen will, muss mit der Software-Entwicklung so früh wie möglich beginnen,Date: 2002/10/18 16:21:27 Revision: 1.96
3.2. <strong>DLX</strong>-ASSEMBLER UND -SIMULATOR 139Assembler-ProgrammProgramm in HochspracheAssembler,CompilerMaschinencodeAbbildung 3.8: Software-Entwicklung auf dem Zielsystemandernfalls würde er wertvolle Marktanteile an die Konkurrenz verlieren. Auf dieProduktionsreife der Hardware kann er meist nicht warten.Um Software für einen noch nicht verfügbaren Prozessortyp zu schreiben, wirdein Simulator verwendet, der zum einen den Befehlssatz und das Verhalten desZielsystems simuliert und zum anderen statistische Daten sammelt, mit denen manz. B. bestimmen kann, wie lange die Ausführung eines Programmes auf einemrealen Zielsystem dauern würde. Dieser Entwicklungsfluss ist in Abbildung 3.9dargestellt.Assembler-Programm /Programm in HochspracheCross-Assembler /Cross-Compiler<strong>DLX</strong>-MaschinencodeSimulatorAusgabedatenStatistikenAbbildung 3.9: Software-Entwicklung auf einem FremdsystemEine ähnliche Situation liegt bei den Übungsaufgaben zum <strong>DLX</strong> vor: der Zielprozessorist nicht verfügbar, dafür aber der Simulator <strong>DLX</strong>sim.Date: 2002/10/18 16:21:27 Revision: 1.96
140 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIEL<strong>DLX</strong>sim ist kommandozeilenorientiert. Dazu ist auf den Rechnern der AbteilungRA ein graphisches Front-End "dlxgui" installiert, das von Herrn Simon Stegmaierprogrammiert und freundlicherweise zur Verfügung gestellt wurde.Eine vollständige Beschreibung aller Simulatorbefehle findet man in der Anleitung„<strong>DLX</strong>sim - Simulator and debugger for <strong>DLX</strong> assembly programs“. Die wichtigstensind:load : Assembler-Datei ladengo : Simulation startenstep : Einzelschrittequit :Ende[f]get [Optionen] : Speicherinhalt anzeigen[f]put [Optionen] : Speicherinhalt verändernstats : Verschiedene Statistiken anzeigenstats reset : Zähler für Statistiken zurücksetzenZu den put und get-Befehlen gibt es verschiedene Varianten. Einige <strong>Beispiel</strong>esind:get 0x100 5 : 5 Worte ab Adresse 100 16 <strong>als</strong> Hexadezimalzahl anzeigenget 0x100 5d : <strong>als</strong> Dezimahlzahl anzeigenget 0x100 5i : <strong>als</strong> Assembleranweisungen anzeigenfget 0x100 : Inhalt von 100 16 <strong>als</strong> Fließkommazahl anzeigenget r1 : Register R1 anzeigenput 0x100 17 : Zahl 17 an Adresse 100 16 schreibenfput f0 3.14 d : Zahl mit doppelter Genauigkeit in F0/F1 schreibenAbschließend soll eine <strong>Beispiel</strong>sitzung mit <strong>DLX</strong>sim beschrieben werden. Gegebensei das Programm aus Abbildung 3.7, das unter dem Dateinamen „prog1.s“abgespeichert ist. Es multipliziert in einer Tabelle ‘x’ mit Gleitkommazahlen doppelterGenauigkeit jede Zahl mit der Konstanten π. Durch Simulation soll herausgefundenwerden,• ob das Programm korrekt funktioniert,• wie viele Takte das Programm zur Ausführung benötigt und• wie oft der bedingte Sprungbefehl „BNEZ R1, loop“ ausgeführt wird undwie oft dabei tatsächlich gesprungen wird.Zunächst wird <strong>DLX</strong>sim gestartet:dlxsimDann wird die Datei „prog1.s“ geladen und assembliert:Date: 2002/10/18 16:21:27 Revision: 1.96
3.2. <strong>DLX</strong>-ASSEMBLER UND -SIMULATOR 141(dlxsim) load prog1.sMit dem get-Befehl, wird überprüft, ob das Programm korrekt geladen wurde:(dlxsim) get 256 9istart : ld f2, a(r0)start+0x4 : addi r1, r0, 0xe0loop : ld f0, a(r1)loop+0x4 : multd f4, f0, f2loop+0x8 : sd a(r1), f4loop+0xc : subi r1, r1, 0x8loop+0x10 : bnez r1, looploop+0x14 : noploop+0x18 : trap 0x0Was hier angezeigt wurde, ist keineswegs die Assembler-Datei „prog1.s“, sondernwurde alleine aus dem Auslesen des simulierten <strong>DLX</strong>-Speichers hergeleitet. Mansieht, dass der Simulator alle Labels speichert und anstelle absoluter AdressenLabelnamen ausgibt, falls dies möglich ist.Das Programm soll zunächst schrittweise ausgeführt werden. Dies geschieht mitdem Befehl „step“:(dlxsim) step 256stopped after single step, pc = start+0x4: addi r1,r0,0xe0(dlxsim) stepstopped after single step, pc = loop: ld f0,a(r1)(dlxsim) stepstopped after single step, pc = loop+0x4: multd f4,f0,f2Beim ersten step-Befehl muss die Startadresse angegeben werden. Die Statuszeile,die jeweils ausgegeben wird, enthält den Stand des Programmzeigers PC und dennächsten auszuführenden Befehl.<strong>DLX</strong>sim soll nun den Rest des Programmlaufes simulieren, ohne zwischendurchmit dem Benutzer zu kommunizieren.(dlxsim) goTRAP # 0 receivedDie Ausgabe zeigt an, dass der Befehl „trap # 0“ erreicht und damit das gesamteProgramm erfolgreich simuliert wurde.Jetzt wird überprüft, ob das Programm korrekt arbeitet, d. h. ob ab der Adresse ‘x’die ersten 28 ganzzahligen Vielfachen von π stehen:Date: 2002/10/18 16:21:27 Revision: 1.96
142 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIEL(dlxsim) fget 8 28dx : 3.141593x+0x8 : 6.283185x+0x10 : 9.424778....x+0xc8 : 81.681409x+0xd0 : 84.823002xtop : 87.964594Die Anzahl der benötigten Taktzyklen und die statistischen Informationen überden „BNEZ“-Befehl erhält man schließlich wie folgt:(dlxsim) stats opcount branchBranches: total 28, taken 27 (96.43% ), untaken 1 (3.57% )INTEGER OPERATIONS====================ADD 0 ADDI 1 ADDU 0 ADDUI 0AND 0 ANDI 0 BEQZ 0 BFPF 0BEPT 0 BNEZ 28 J 0 JAL 0....Total integer operations = 143FLOATING POINT OPERATIONS===========================ADDD 0 ADDF 0 CVTD2F 0 CVTD2I 0CVTF2D 0 CVTF2I 0 CVTI2D 0 CVTI2F 0....Total floating point operations = 28Total operations = 171Total cycles = 311Date: 2002/10/18 16:21:27 Revision: 1.96
3.2. <strong>DLX</strong>-ASSEMBLER UND -SIMULATOR 1433.2.3 Praktische HinweiseZum Abschluss sei der Leser an die folgenden Fallstricke erinnert:1. R0 ist kein Register, sondern repräsentiert die Konstante 0 (vgl. <strong>Kapitel</strong> 3.1).2. Es gibt keine Befehle, um Konstanten in Integer-Register zu laden, bzw.um Daten zwischen Integer-Registern zu verschieben. Stattdessen müssenarithmetische Befehle verwendet werden (vgl. <strong>Kapitel</strong> 3.1.1).3. Zur Multiplikation und Division von Integer-Zahlen müssen Gleitkomma-Register verwendet werden (vgl. <strong>Kapitel</strong> 3.1.2).4. Adressen und Konstanten können nur mit einer geringeren Wortbreite <strong>als</strong>32 Bit direkt geladen werden (vgl. <strong>Kapitel</strong> 3.1.2).5. Es sind nur ausgerichtete Speicherzugriffe erlaubt (vgl. <strong>Kapitel</strong> 3.1.1). Andernfallstritt zur Laufzeit eine Unterbrechung auf und das Programm kannnicht weiter ausgeführt werden. Man beachte, dass dabei die effektive Adresseausschlaggebend ist. Um den Befehl „LW R1, 17 (R2)“ ausführen zukönnen muss R2 <strong>als</strong>o 3, 7, 11 ... enthalten.6. Bedingt durch Pipelining wird jeder auf einen Sprungbefehl folgende Befehlausgeführt („delayed branching“). Um nächtelange Fehlersuchen zuvermeiden, sollte man sich anfangs angewöhnen, hinter jedem Sprungbefehlein „NOP“ einzufügen (vgl. <strong>Kapitel</strong> 3.1.3).Date: 2002/10/18 16:21:27 Revision: 1.96
144 KAPITEL 3. DER <strong>DLX</strong> ALS <strong>RISC</strong>-BEISPIELDate: 2002/10/18 16:21:27 Revision: 1.96