MIPS Sitzungssprache
*Die klassische RISC Architektur Powering Networking und Embedded Systeme weltweit *
MIPS (Microprocessor ohne Interlocked Pipelined Stages) stellt eine der einflussreichsten und dauerhaften Prozessorarchitekturen in der Rechengeschichte dar. Ursprünglich von MIPS Computer Systems in den 1980er Jahren entwickelt, hat diese reduzierte Unterrichts-Set-Computer (RISC) Architektur seine Relevanz durch Jahrzehnte der technologischen Entwicklung beibehalten, derzeit dominieren Networking-Geräte mit über 90% Marktanteil an Routern und Switchen, während weiterhin kritische Rollen in eingebetteten Systemen, Telekommunikation und Computer-Architektur Bildung dienen.
Architektur Überblick
MIPS verkörpert die Grundprinzipien des RISC Designs mit einem sauberen, orthogonalen Befehlssatz, der die Einfachheit und Leistungsvorhersage priorisiert. Die Architektur verfügt über ein Load-store-Design, bei dem arithmetische Operationen ausschließlich an Registern arbeiten, mit separaten Anweisungen für den Speicherzugriff. Dieser Ansatz vereinfacht die Implementierung der Prozessoren und ermöglicht gleichzeitig hohe Taktfrequenzen und effiziente Pipelinierung.
Schlüsselprinzipien
Die MIPS-Architektur zeigt mehrere Grundprinzipien, die die Prozessorentwicklung in der gesamten Branche beeinflusst haben. Der Befehlssatz unterhält eine feste 32-Bit-Anweisungslänge, vereinfacht den Befehls-Fetch und decodiert die Logik und ermöglicht einen effizienten Befehls-Caching. Alle Anleitungen führen in einer konstanten Anzahl von Taktzyklen durch, was die Leistungsanalyse und Optimierung vorhersehbarer macht als komplexe Befehlsset-Computer (CISC).
Die Architektur verwendet eine große Registerdatei mit 32 Universalregistern, reduziert den Speicherverkehr und ermöglicht eine effiziente Codegenerierung durch Compiler. Die einfachen Adressierungsmodi und die regelmäßigen Befehlsformate minimieren die Hardware-Komplexität und bieten eine ausreichende Flexibilität für verschiedene Programmieraufgaben. Der verzögerte Verzweigungsmechanismus, der für Programmierer zunächst herausfordert, ermöglicht eine effiziente Pipeline-Umsetzung, indem Verzweigungsverzögerungen in Hardware beseitigt werden.
Historischer Kontext und Evolution
MIPS entstand während der RISC-Revolution der 1980er Jahre, im Wettbewerb mit anderen wegweisenden Architekturen wie SPARC und ARM. Die Architektur erlangte in den 1990er und 2000er Jahren beträchtliche Traktion in Workstations, Servern und Embedded Systemen. Während x86 Prozessoren den Desktop Computing dominierten und ARM mobile Märkte eroberte, fand MIPS seine Nische in Netzwerkinfrastruktur und spezialisierte Embedded-Anwendungen, wo seine vorhersehbare Leistung und effiziente Umsetzung als vorteilhaft erwies.
Die Architektur hat sich durch mehrere Generationen entwickelt, von der ursprünglichen MIPS I bis MIPS V, mit den modernen MIPS32 und MIPS64 Spezifikationen, die zeitgenössische Funktionen bieten und gleichzeitig Rückwärtskompatibilität. Zu den jüngsten Entwicklungen zählen die MIPS32/64 Release 6 Spezifikation, die die Architektur mit verbesserter Befehlscodierung und erweiterten Funktionen für aktuelle Anwendungen modernisiert.
Registrieren Architektur
MIPS bietet 32 Universal-Register, jede 32 Bit breite in MIPS32 oder 64 Bit breite in MIPS64-Implementierungen. Die Registerdatei stellt eine der wichtigsten Stärken der Architektur dar, die eine Vielzahl von Speichern für die Compiler-Optimierung bietet und gleichzeitig eine angemessene Implementierungskomplexität gewährleistet.
Registrieren Set und Namenskonventionen
| | Register | Number | Name | Description | Preserved | | | --- | --- | --- | --- | --- | | | $zero | $0 | zero | Hard-wired zero | N/A | | | | $at | $1 | at | Assembler temporary | No | | | | $v0-$v1 | $2-$3 | v0-v1 | Function return values | No | | | | $a0-$a3 | $4-$7 | a0-a3 | Function arguments | No | | | | $t0-$t7 | $8-$15 | t0-t7 | Temporary registers | No | | | | $s0-$s7 | $16-$23 | s0-s7 | Saved registers | Yes | | | | $t8-$t9 | $24-$25 | t8-t9 | More temporary registers | No | | | | $k0-$k1 | $26-$27 | k0-k1 | Kernel registers | N/A | | | | $gp | $28 | gp | Global pointer | N/A | | | | $sp | $29 | sp | Stack pointer | Yes | | | | $fp | $30 | fp | Frame pointer | Yes | | | | $ra | $31 | ra | Return address | No | |
Registrieren Nutzungsübereinkommen
Die MIPS-Konvention legt spezifische Rollen für Register fest, um die Kompatibilität zwischen verschiedenen Compilern und Softwarekomponenten zu gewährleisten. Argument registriert $a0-$a3 passieren die ersten vier Funktionsparameter, mit zusätzlichen Argumenten auf dem Stack übergeben. Rückgabewerte verwenden $v0 für einzelne Werte und $v0-$v1 für 64-Bit-Rücksendungen auf MIPS32-Systemen.
Temporäre Register $t0-$t9 bieten Platz für Berechnungen und müssen nicht über Funktion Anrufe erhalten bleiben, so dass sie ideal für Zwischenberechnungen und Zwischenspeicherung. Gespeicherte Register $s0-$s7 müssen durch aufgerufene Funktionen erhalten werden, so dass sie geeignet für Variablen, die mehrere Funktionsaufrufe oder Schleifen Iterationen überspannen.
Der Stackpointer $sp muss immer auf gültigen Stack-Speicher zeigen und wird typischerweise durch aufgerufene Funktionen eingestellt, um lokale Speicher zuzuordnen. Der Framepointer $fp hält optional einen festen Referenzpunkt innerhalb des aktuellen Stackrahmens auf, wodurch der Zugriff auf lokale Variablen und Parameter in komplexen Funktionen vereinfacht wird. Das Rückgabeadressenregister $ra hält die Rückgabeadresse für Funktionsanrufe, automatisch durch Sprung- und Linksanweisungen gesetzt.
Sonderregister
Neben der allgemeinen Registerdatei umfassen MIPS-Prozessoren mehrere Spezialregister zur Systemsteuerung und Statusüberwachung. Der Programmzähler (PC) verfolgt die aktuelle Befehlsadresse, ist aber nicht direkt über normale Anweisungen zugänglich. Die HI- und LO-Register speichern die Ergebnisse von Multiplikations- und Divisionsoperationen, die durch besondere Bewegungsanweisungen zugänglich sind.
Coprozessor 0 (CP0)-Register bieten Systemsteuerungsfunktionalität einschließlich Ausnahme-Handling, Speicherverwaltung und Prozessorkonfiguration. Diese Register ermöglichen die Implementierung des Betriebssystems und die Programmierung auf Systemebene, erfordern jedoch einen privilegierten Zugriff in den meisten Implementierungen.
Instruktion Set Architektur
Der MIPS-Anweisungssatz bietet eine umfassende Grundlage für das allgemeine Computing bei gleichzeitiger Aufrechterhaltung der Einfachheit und Ordnungsmäßigkeit, die RISC-Architekturen charakterisiert. Der Basisanweisungssatz umfasst arithmetische, logische, Speicherzugriffe und Steuerungsabläufe, die für die Implementierung komplexer Softwaresysteme ausreichend sind.
Instruktionsformate
MIPS verwendet drei grundlegende Befehlsformate, die verschiedene Arten von Operationen kodieren und gleichzeitig konsistente Feldpositionen für gemeinsame Elemente wie Register-Spezifikationen und Opcodes beibehalten.
R-Type Anleitung (Register)
31 26 25 21 20 16 15 11 10 6 5 0
[opcode] [rs] [rt] [rd] [shamt] [funct]
```_
R-Anweisungen führen Operationen zwischen Registern, mit zwei Quellregistern (rs, rt) und einem Zielregister (rd). Das Shamt-Feld gibt Verschiebungsbeträge für Verschiebungsvorgänge an, während das Funct-Feld für verschiedene Operationen innerhalb desselben Primär-Opcodes zusätzlichen Opcode-Raum bietet.
```asm
add $t0, $t1, $t2 # $t0 = $t1 + $t2
sub $s0, $s1, $s2 # $s0 = $s1 - $s2
and $a0, $a1, $a2 # $a0 = $a1 & $a2
or $v0, $v1, $t0 # $v0 = $v1|$t0
sll $t3, $t4, 4 # $t3 = $t4 << 4
```_
#### I-Typ Anweisungen (unmittelbar)
31 26 25 21 20 16 15 0 [opcode] [rs] [rt] [immediate]
I-Typ-Anweisungen funktionieren auf einem Register und einem 16-Bit sofortigen Wert. Dieses Format umfasst sofortige arithmetische, Last- und Speichervorgänge und bedingte Zweige. Das unmittelbare Feld wird für arithmetische Operationen auf 32 Bit erweitert.
```asm
addi $t0, $t1, 100 # $t0 = $t1 + 100
lw $s0, 8($sp) # $s0 = memory[$sp + 8]
sw $a0, 12($fp) # memory[$fp + 12] = $a0
beq $t0, $t1, label # if $t0 == $t1, branch to label
```_
#### J-Type Anleitung (Jump)
31 26 25 0 [opcode] [address] ```_
J-Anweisungen führen bedingungslose Sprünge mit einem 26-Bit-Adressenfeld durch. Die Zieladresse wird durch Kombination des Adreßfeldes mit den oberen Bits des Programmzählers gebildet, wodurch Sprünge innerhalb eines 256MB-Gebiets ermöglicht werden.
asm
j target # jump to target
jal function # jump to function, save return address
_
Arithmetische und Logische Anweisungen
MIPS bietet eine umfassende Reihe von arithmetischen und logischen Anweisungen für Register- und Register-immediate Operationen. Diese Anweisungen bilden die rechnerische Grundlage für mathematische Operationen, Bitmanipulation und Adressberechnungen.
Grundlegende arithmetische Operationen
```asm
Addition and subtraction
add $rd, $rs, $rt # $rd = $rs + $rt addi $rt, $rs, imm # $rt = $rs + sign_extend(imm) addu $rd, $rs, $rt # $rd = $rs + $rt (unsigned, no overflow) addiu $rt, $rs, imm # $rt = $rs + sign_extend(imm) (unsigned) sub $rd, $rs, $rt # $rd = $rs - $rt subu $rd, $rs, $rt # $rd = $rs - $rt (unsigned, no overflow)
Multiplication and division
mult $rs, $rt # HI:LO = $rs * $rt (signed) multu $rs, $rt # HI:LO = $rs * $rt (unsigned) div $rs, $rt # LO = $rs / $rt, HI = $rs % $rt (signed) divu $rs, $rt # LO = $rs / $rt, HI = $rs % $rt (unsigned) mfhi $rd # $rd = HI mflo $rd # $rd = LO mthi $rs # HI = $rs mtlo $rs # LO = $rs ```_
Logische Operationen
```asm
Bitwise operations
and $rd, $rs, $rt # $rd = $rs & $rt andi $rt, $rs, imm # $rt = $rs & zero_extend(imm) or $rd, $rs, $rt # $rd = $rs|$rt ori $rt, $rs, imm # $rt = $rs|zero_extend(imm) xor $rd, $rs, $rt # $rd = $rs ^ $rt xori $rt, $rs, imm # $rt = $rs ^ zero_extend(imm) nor $rd, $rs, $rt # $rd = ~($rs|$rt)
Shift operations
sll $rd, $rt, shamt # $rd = $rt << shamt sllv $rd, $rt, $rs # $rd = $rt << ($rs & 0x1F) srl $rd, $rt, shamt # $rd = $rt >> shamt (logical) srlv $rd, $rt, $rs # $rd = $rt >> ($rs & 0x1F) (logical) sra $rd, $rt, shamt # $rd = $rt >> shamt (arithmetic) srav $rd, $rt, $rs # $rd = $rt >> ($rs & 0x1F) (arithmetic) ```_
Vergleich Operationen
```asm
Set on less than
slt $rd, $rs, $rt # $rd = ($rs < $rt) ? 1 : 0 (signed) slti $rt, $rs, imm # $rt = ($rs < sign_extend(imm)) ? 1 : 0 sltu $rd, $rs, $rt # $rd = ($rs < $rt) ? 1 : 0 (unsigned) sltiu $rt, $rs, imm # $rt = ($rs < sign_extend(imm)) ? 1 : 0 (unsigned) ```_
Speicherzugriff Anleitung
MIPS verwendet eine Load-store-Architektur, in der arithmetische Operationen ausschließlich auf Registern arbeiten, mit separaten Anweisungen zur Übertragung von Daten zwischen Registern und Speicher. Dieses Design vereinfacht die Implementierung der Prozessoren und ermöglicht eine effiziente Cache- und Speicheroptimierung.
Ladeanleitung
Ladebefehle übertragen Daten von Speicher zu Registern, mit Unterstützung für verschiedene Datengrößen und Zeichenerweiterung Optionen. Die effektive Adresse wird berechnet, indem ein 16-Bit signierter Offset zu einem Basisregisterwert addiert wird.
```asm
Load word (32-bit)
lw $rt, offset($rs) # $rt = memory[$rs + offset]
Load halfword (16-bit)
lh $rt, offset($rs) # $rt = sign_extend(memory[$rs + offset][15:0]) lhu $rt, offset($rs) # $rt = zero_extend(memory[$rs + offset][15:0])
Load byte (8-bit)
lb $rt, offset($rs) # $rt = sign_extend(memory[$rs + offset][7:0]) lbu $rt, offset($rs) # $rt = zero_extend(memory[$rs + offset][7:0])
Load upper immediate
lui $rt, imm # $rt = imm << 16
Load word left/right (unaligned access)
lwl $rt, offset($rs) # Load left portion of unaligned word lwr $rt, offset($rs) # Load right portion of unaligned word ```_
Instruktionen speichern
Speicherhinweise übertragen Daten von Registern in den Speicher und unterstützen die gleichen Datengrößen wie Lastanweisungen. Der gespeicherte Wert wird aus dem Quellregister mit entsprechender Maskierung für kleinere Datengrößen entnommen.
```asm
Store word (32-bit)
sw $rt, offset($rs) # memory[$rs + offset] = $rt
Store halfword (16-bit)
sh $rt, offset($rs) # memory[$rs + offset][15:0] = $rt[15:0]
Store byte (8-bit)
sb $rt, offset($rs) # memory[$rs + offset][7:0] = $rt[7:0]
Store word left/right (unaligned access)
swl $rt, offset($rs) # Store left portion of unaligned word swr $rt, offset($rs) # Store right portion of unaligned word ```_
Adressierungsmodi
MIPS unterstützt mehrere Adressierungsmodi durch Kombinationen von Anweisungen und Registernutzungsmustern. Basisadressierung verwendet ein Register plus Offset für den Zugriff auf Datenstrukturen und Stackvariablen. Indizierte Adressierung kombiniert zwei Register für den Array-Zugang, die typischerweise durch Addition und anschließende Last-/Speicheroperationen realisiert werden.
```asm
Base addressing
lw $t0, 8($sp) # Load from stack (base + offset) sw $a0, 12($fp) # Store to frame (base + offset)
Indexed addressing (requires address calculation)
add $t1, $s0, $t2 # Calculate array[index] address lw $t0, 0($t1) # Load array element
PC-relative addressing (using labels)
la $t0, data_label # Load address of label lw $t1, 0($t0) # Load data at label ```_
Steuerung der Strömungsanleitung
Steuerungsflussanleitungen verwalten Programmausführung durch die Implementierung von bedingten und bedingungslosen Zweigen, Funktionsaufrufen und Rückgaben. MIPS bietet eine reiche Reihe von Zweiganweisungen, die Register und Transfersteuerung basierend auf den Ergebnissen vergleichen.
Bedingte Branchanleitung
```asm
Equality branches
beq $rs, $rt, label # if ($rs == $rt) goto label bne $rs, $rt, label # if ($rs != $rt) goto label
Zero comparison branches
beqz $rs, label # if ($rs == 0) goto label (pseudo) bnez $rs, label # if ($rs != 0) goto label (pseudo)
Comparison branches
blez $rs, label # if ($rs <= 0) goto label bgtz $rs, label # if ($rs > 0) goto label bltz $rs, label # if ($rs < 0) goto label bgez $rs, label # if ($rs >= 0) goto label
Branch and link variants
bltzal $rs, label # if ($rs < 0) \\{ $ra = PC + 8; goto label \\} bgezal $rs, label # if ($rs >= 0) \\{ $ra = PC + 8; goto label \\} ```_
bedingungslose Sprunganleitung
```asm
Jump instructions
j target # goto target jal target # $ra = PC + 8; goto target jr $rs # goto $rs jalr $rd, $rs # $rd = PC + 8; goto $rs
Common jump patterns
jal function # Call function jr $ra # Return from function ```_
Ablagefächer
MIPS implementiert verzögerte Zweige, in denen die Anweisung unmittelbar nach einem Zweig oder Sprung ausgeführt wird, unabhängig davon, ob der Zweig genommen wird. Dieses Design vereinfacht die Pipeline-Implementierung, erfordert aber eine sorgfältige Unterrichtsplanung.
```asm
Branch with delay slot
beq $t0, $t1, target add $t2, $t3, $t4 # This instruction always executes
Jump with delay slot
j function nop # Delay slot (no operation)
Optimized delay slot usage
beq $t0, $t1, skip add $s0, $s1, $s2 # Useful work in delay slot skip: ```_
Pseudoinstruktionen
MIPS Montagesprache umfasst zahlreiche Pseudoinstruktionen, die sich auf eine oder mehrere tatsächliche Anleitungen erweitern und bequeme Mnemonics für gemeinsame Operationen bereitstellen und die Montageprogrammierung vereinfachen.
Datenbewegung Pseudoinstruktionen
```asm
Register operations
move $rd, $rs # add $rd, $rs, $zero nop # sll $zero, $zero, 0 clear $rd # add $rd, $zero, $zero
Immediate loading
li $rt, imm # Load 32-bit immediate (may use lui + ori) la $rt, label # Load address of label
Examples of li expansion:
li $t0, 0x1234 # ori $t0, $zero, 0x1234 li $t1, 0x12345678 # lui $t1, 0x1234; ori $t1, $t1, 0x5678 ```_
Arithmetische Pseudoinstruktionen
```asm
Negation
neg $rd, $rs # sub $rd, $zero, $rs negu $rd, $rs # subu $rd, $zero, $rs
Absolute value
abs $rd, $rs # Complex expansion with branches
Multiplication with immediate
mul $rd, $rs, imm # Load immediate, then mult/mflo
Division with immediate
div $rd, $rs, imm # Load immediate, then div/mflo rem $rd, $rs, $rt # div $rs, $rt; mfhi $rd ```_
Vergleich Pseudoinstruktionen
```asm
Set operations
seq $rd, $rs, $rt # Set if equal sne $rd, $rs, $rt # Set if not equal sge $rd, $rs, $rt # Set if greater or equal sgt $rd, $rs, $rt # Set if greater than sle $rd, $rs, $rt # Set if less or equal
Branch pseudoinstructions
blt $rs, $rt, label # Branch if less than bgt $rs, $rt, label # Branch if greater than ble $rs, $rt, label # Branch if less or equal bge $rs, $rt, label # Branch if greater or equal ```_
Programmierbeispiele
Hallo Weltprogramm
```asm .data hello_msg: .asciiz "Hello, MIPS World!\n"
.text .globl main
main: # Print string system call li $v0, 4 # sys_print_string la $a0, hello_msg # load string address syscall # system call
# Exit program
li $v0, 10 # sys_exit
syscall # system call
```_
Faktorfunktion
```asm .text .globl factorial
Calculate factorial of n
Input: $a0 = n
Output: $v0 = n!
factorial: # Base case: if n <= 1, return 1 li $t0, 1 ble $a0, $t0, fact_base
# Save registers
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $a0, 0($sp)
# Recursive call: factorial(n-1)
addi $a0, $a0, -1
jal factorial
# Restore n and calculate n * factorial(n-1)
lw $a0, 0($sp)
lw $ra, 4($sp)
addi $sp, $sp, 8
mult $a0, $v0 # n * factorial(n-1)
mflo $v0 # result in $v0
jr $ra
fact_base: li $v0, 1 # return 1 jr $ra ```_
Array Sum Funktion
```asm .text .globl array_sum
Calculate sum of array elements
Input: $a0 = array address, $a1 = array length
Output: $v0 = sum
array_sum: li $v0, 0 # sum = 0 li $t0, 0 # index = 0
sum_loop: bge $t0, $a1, sum_done # if index >= length, exit
sll $t1, $t0, 2 # t1 = index * 4 (word size)
add $t2, $a0, $t1 # t2 = array + offset
lw $t3, 0($t2) # load array[index]
add $v0, $v0, $t3 # sum += array[index]
addi $t0, $t0, 1 # index++
j sum_loop
sum_done: jr $ra # return sum in $v0 ```_
String Länge Funktion
```asm .text .globl strlen
Calculate string length
Input: $a0 = string address
Output: $v0 = string length
strlen: move $t0, $a0 # save original address li $v0, 0 # length = 0
strlen_loop: lb $t1, 0($t0) # load byte beqz $t1, strlen_done # if null terminator, done
addi $v0, $v0, 1 # increment length
addi $t0, $t0, 1 # advance pointer
j strlen_loop
strlen_done: jr $ra # return length in $v0 ```_
MIPS32 und MIPS64 Erweiterungen
MIPS64 Architektur
MIPS64 erweitert die Basisarchitektur, um 64-Bit-Betriebe zu unterstützen und gleichzeitig die Kompatibilität mit 32-Bit-Code zu gewährleisten. Die Registerdatei erweitert sich auf 64 Bit pro Register, und weitere Anweisungen behandeln 64-Bit-Arithmetik und Speicheroperationen.
```asm
64-bit arithmetic (MIPS64)
dadd $rd, $rs, $rt # 64-bit addition daddi $rt, $rs, imm # 64-bit add immediate dsub $rd, $rs, $rt # 64-bit subtraction dmult $rs, $rt # 64-bit multiplication ddiv $rs, $rt # 64-bit division
64-bit memory operations
ld $rt, offset($rs) # Load doubleword (64-bit) sd $rt, offset($rs) # Store doubleword (64-bit) ldl $rt, offset($rs) # Load doubleword left ldr $rt, offset($rs) # Load doubleword right sdl $rt, offset($rs) # Store doubleword left sdr $rt, offset($rs) # Store doubleword right
64-bit shifts
dsll $rd, $rt, shamt # Doubleword shift left logical dsrl $rd, $rt, shamt # Doubleword shift right logical dsra $rd, $rt, shamt # Doubleword shift right arithmetic dsll32 $rd, $rt, shamt # Doubleword shift left logical + 32 dsrl32 $rd, $rt, shamt # Doubleword shift right logical + 32 dsra32 $rd, $rt, shamt # Doubleword shift right arithmetic + 32 ```_
Floating-Point-Betriebe
MIPS Prozessoren umfassen typischerweise einen Floating-Point-Koprozessor (FPU), der IEEE 754-konforme Floating-Point-Arithmetic bietet. Die FPU verfügt über eine eigene Registerdatei und einen Befehlssatz.
```asm
Single-precision floating-point
add.s $f0, $f1, $f2 # $f0 = $f1 + $f2 (single) sub.s $f0, $f1, $f2 # $f0 = $f1 - $f2 (single) mul.s $f0, $f1, $f2 # $f0 = $f1 * $f2 (single) div.s $f0, $f1, $f2 # $f0 = $f1 / $f2 (single)
Double-precision floating-point
add.d $f0, $f2, $f4 # $f0:$f1 = $f2:$f3 + $f4:$f5 (double) sub.d $f0, $f2, $f4 # $f0:$f1 = $f2:$f3 - $f4:$f5 (double) mul.d $f0, $f2, $f4 # $f0:$f1 = $f2:$f3 * $f4:$f5 (double) div.d $f0, $f2, $f4 # $f0:$f1 = $f2:$f3 / $f4:$f5 (double)
Floating-point load/store
lwc1 $f0, offset($rs) # Load word to FPU register swc1 $f0, offset($rs) # Store word from FPU register ldc1 $f0, offset($rs) # Load doubleword to FPU register sdc1 $f0, offset($rs) # Store doubleword from FPU register
Floating-point comparisons
c.eq.s $f0, $f1 # Compare equal (single) c.lt.s $f0, $f1 # Compare less than (single) c.le.s $f0, $f1 # Compare less or equal (single) bc1t label # Branch if FP condition true bc1f label # Branch if FP condition false ```_
Systemprogrammierung
Außergewöhnliche Handhabung
MIPS bietet einen umfassenden Ausnahme-Handling-Mechanismus für die Implementierung von Betriebssystemen und die Handhabung von Laufzeitfehlern. Ausnahmen übertragen Steuerung auf vordefinierte Griffadressen mit minimalem Hardware-Überkopf.
```asm
Exception vector addresses (typical)
0x80000000: Reset/NMI
0x80000180: General exception
0x80000200: Interrupt
.ktext 0x80000180 exception_handler: # Save all registers (kernel exception handler) .set noat move $k0, $at # save $at in $k0 .set at
# Save registers to kernel stack
la $k1, kernel_stack
sw $v0, 0($k1)
sw $v1, 4($k1)
sw $a0, 8($k1)
# ... save all registers
# Determine exception cause
mfc0 $k0, $13 # read Cause register
andi $k0, $k0, 0x7C # extract exception code
srl $k0, $k0, 2 # shift to get code
# Jump to specific handler
la $k1, exception_table
sll $k0, $k0, 2 # multiply by 4 for word offset
add $k1, $k1, $k0
lw $k1, 0($k1)
jr $k1
System call handler
syscall_handler: # $v0 contains system call number # $a0-$a3 contain arguments
# Implement system call dispatch
beq $v0, 1, sys_print_int
beq $v0, 4, sys_print_string
beq $v0, 10, sys_exit
# ... other system calls
# Return from exception
mfc0 $k0, $14 # read EPC (return address)
addi $k0, $k0, 4 # skip syscall instruction
mtc0 $k0, $14 # update EPC
# Restore registers
# ... restore all registers
eret # return from exception
```_
Speicherverwaltung
```asm
TLB (Translation Lookaside Buffer) management
tlb_miss_handler: # Handle TLB miss exception mfc0 $k0, $8 # read BadVAddr register mfc0 $k1, $10 # read EntryHi register
# Look up page table entry
# ... page table lookup code
# Load TLB entry
mtc0 $k0, $2 # write EntryLo0
mtc0 $k1, $3 # write EntryLo1
mtc0 $t0, $10 # write EntryHi
tlbwr # write TLB entry
eret # return from exception
Cache management
cache_flush: # Flush instruction cache li $t0, 0x10000 # cache size li $t1, 32 # cache line size
flush_loop: cache 0x0, 0($t0) # index invalidate I-cache subu $t0, $t0, $t1 # next cache line bgez $t0, flush_loop
jr $ra
```_
Montage Programmiertechniken
Funktion Calling Convention
MIPS folgt einer Standardanrufkonvention, die die Kompatibilität zwischen verschiedenen Compilern und Bibliotheken gewährleistet. Das Verständnis dieser Konvention ist wesentlich für das Schreiben von Montagefunktionen, die Schnittstelle mit hochrangigen Sprachcode.
```asm
Standard function prologue
function_name: # Save return address and callee-saved registers addi $sp, $sp, -32 # allocate stack frame sw $ra, 28($sp) # save return address sw $fp, 24($sp) # save frame pointer sw $s0, 20($sp) # save callee-saved register sw $s1, 16($sp) # save callee-saved register addi $fp, $sp, 32 # set frame pointer
# Function body
# Arguments in $a0-$a3, return value in $v0-$v1
# Use $t0-$t9 for temporary values
# Use $s0-$s7 for values that must survive function calls
# Function epilogue
lw $ra, 28($sp) # restore return address
lw $fp, 24($sp) # restore frame pointer
lw $s0, 20($sp) # restore callee-saved register
lw $s1, 16($sp) # restore callee-saved register
addi $sp, $sp, 32 # deallocate stack frame
jr $ra # return to caller
```_
Optimierte Speicheroperationen
```asm
Optimized memory copy (word-aligned)
memcpy_words: # $a0 = destination, $a1 = source, $a2 = word count beqz $a2, copy_done # if count == 0, done
copy_loop: lw $t0, 0($a1) # load word from source sw $t0, 0($a0) # store word to destination addi $a0, $a0, 4 # advance destination addi $a1, $a1, 4 # advance source addi $a2, $a2, -1 # decrement count bnez $a2, copy_loop # continue if count > 0
copy_done: jr $ra
Unrolled loop for better performance
unrolled_copy: # Copy 4 words at a time andi $t0, $a2, 3 # remainder when divided by 4 srl $a2, $a2, 2 # divide count by 4 beqz $a2, copy_remainder
unroll_loop: lw $t1, 0($a1) # load 4 words lw $t2, 4($a1) lw $t3, 8($a1) lw $t4, 12($a1)
sw $t1, 0($a0) # store 4 words
sw $t2, 4($a0)
sw $t3, 8($a0)
sw $t4, 12($a0)
addi $a0, $a0, 16 # advance by 4 words
addi $a1, $a1, 16
addi $a2, $a2, -1 # decrement loop count
bnez $a2, unroll_loop
copy_remainder: # Handle remaining words beqz $t0, copy_done # ... handle 1-3 remaining words jr $ra ```_
Datenstruktur Manipulation
```asm
Linked list insertion
list_insert: # $a0 = list head pointer address, $a1 = new node lw $t0, 0($a0) # load current head sw $t0, 4($a1) # new_node->next = head sw $a1, 0($a0) # head = new_node jr $ra
Binary search in sorted array
binary_search: # $a0 = array, $a1 = length, $a2 = target # Returns: $v0 = index (-1 if not found)
li $t0, 0 # left = 0
move $t1, $a1 # right = length
search_loop: bge $t0, $t1, not_found # if left >= right, not found
add $t2, $t0, $t1 # mid = (left + right) / 2
srl $t2, $t2, 1
sll $t3, $t2, 2 # calculate array[mid] address
add $t3, $a0, $t3
lw $t4, 0($t3) # load array[mid]
beq $t4, $a2, found # if array[mid] == target, found
blt $t4, $a2, search_right
# Search left half
move $t1, $t2 # right = mid
j search_loop
search_right: addi $t0, $t2, 1 # left = mid + 1 j search_loop
found: move $v0, $t2 # return index jr $ra
not_found: li $v0, -1 # return -1 jr $ra ```_
Leistungsoptimierung
Pipeline Optimierung
MIPS-Prozessoren verwenden Befehlspipeline, um eine hohe Leistung zu erreichen, aber Pipeline-Gefahren können Effizienz reduzieren. Das Verständnis dieser Gefahren ermöglicht eine bessere Codegenerierung und Optimierung.
```asm
Poor scheduling - data hazard
lw $t0, 0($a0) add $t1, $t0, $t2 # stall: $t0 not ready sw $t1, 4($a0) # stall: $t1 not ready
Better scheduling - avoid hazards
lw $t0, 0($a0) lw $t3, 8($a0) # independent instruction add $t1, $t0, $t2 # $t0 now ready add $t4, $t3, $t2 # independent operation sw $t1, 4($a0) sw $t4, 12($a0) ```_
Optimierung der Bremse
```asm
Minimize branch penalties
Poor: many branches
beq $t0, $zero, skip1 add $s0, $s0, 1 skip1: beq $t1, $zero, skip2 add $s1, $s1, 1 skip2:
Better: combine conditions
or $t2, $t0, $t1 bnez $t2, skip_all add $s0, $s0, 1 add $s1, $s1, 1 skip_all:
Use conditional moves when available
Instead of: if (a > b) c = a; else c = b;
slt $t0, $a1, $a0 # $t0 = (b < a) movn $a2, $a0, $t0 # if $t0 != 0, $a2 = $a0 movz $a2, $a1, $t0 # if $t0 == 0, $a2 = $a1 ```_
Debugging- und Entwicklungswerkzeuge
GDB Integration
MIPS-Montageprogramme können mithilfe von GDB mit MIPS-Unterstützung debuggiert werden und bieten leistungsstarke Debugging-Funktionen für Entwicklung und Test.
```bash
Compile with debug information
mips-linux-gnu-gcc -g -o program program.s
Debug with GDB
mips-linux-gnu-gdb program
GDB commands for MIPS
(gdb) info registers # show all registers (gdb) info registers $t0 # show specific register (gdb) x/10i $pc # disassemble 10 instructions at PC (gdb) stepi # single step instruction (gdb) break *0x400000 # set breakpoint at address (gdb) print $v0 # print register value ```_
Simulation und Emulation
MIPS-Programme können mit verschiedenen Simulatoren und Emulatoren getestet werden, was die Entwicklung ohne physische Hardware ermöglicht.
```bash
SPIM simulator
spim -file program.s
MARS (MIPS Assembler and Runtime Simulator)
java -jar Mars.jar program.s
QEMU system emulation
qemu-system-mips -M malta -kernel vmlinux
QEMU user mode emulation
qemu-mips program ```_
Best Practices und gemeinsame Muster
Fehlerbehebung
```asm
Function with error checking
safe_divide: # $a0 = dividend, $a1 = divisor # Returns: $v0 = result, $v1 = error code (0 = success)
beqz $a1, divide_by_zero # check for division by zero
div $a0, $a1 # perform division
mflo $v0 # get quotient
li $v1, 0 # success
jr $ra
divide_by_zero: li $v0, 0 # result = 0 li $v1, 1 # error code = 1 jr $ra ```_
Ressourcenmanagement
```asm
Stack-based local storage
allocate_locals: # Allocate space for local variables addi $sp, $sp, -16 # allocate 16 bytes
# Use stack space
sw $t0, 0($sp) # local variable 1
sw $t1, 4($sp) # local variable 2
sw $t2, 8($sp) # local variable 3
sw $t3, 12($sp) # local variable 4
# ... function body
# Deallocate space
addi $sp, $sp, 16 # restore stack pointer
jr $ra
```_