Zum Inhalt

MIPS Sitzungssprache

generieren

*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

```_