2016-04-10 14 views
-1

Ich arbeite an einem Projekt für eine meiner Klassen, bei dem C-Code in MIPS-Assembly übersetzt wird. Ich habe diesen Code Probleme übersetzen:Zugriffsregister, dessen Nummer in einem anderen Register gespeichert ist

r[extract(ir,15,11)] = aluout; 

Grundsätzlich r [] ist ein Array, das die Register in C repräsentiert Wie Sie sehen können, bestimmt sie, welche basierend auf dem Ergebnis aus der extract Funktion für den Zugriff registrieren. Gibt es so etwas in MIPS? Der einzige Weg, wie ich es mir vorstellen kann, ist, den Wert zu nehmen, den ich von der Extraktionssubroutine erhalten werde, und sie mit allen Registernummern zu vergleichen. Die C-Darstellung würde dies wie folgt aussehen:

regNum = extract(ir, 15, 11); 
if (regNum == 1) { 
    r[1] = aluout; 
} else if (regNum == 2) { 
    r[2] = aluout; 
} else if (regNum == 3) { 
    r[3] = aluout; 
} ... 

Irgendwelche Ideen? Ist das der einzige Weg?

+1

Umm, können Sie ein Array indizieren. Sie können die Rohregister jedoch nicht indizieren. – Jester

+0

Ja, ich weiß. Der C-Code ist etwas, was unser Professor uns gesagt hat, dass wir in MIPS übersetzen sollen. r [index] stellt nur das Register $ [index] dar, wenn Sie es in MIPS – wKavey

+3

übersetzen würden. Sie schreiben also ein MIPS-Assembly-Programm, das eine (MIPS?) CPU emulieren soll. Ich würde nur die emulierten Register in einem Array behalten, wie Sie es bei C tun würden. Sie können wahrscheinlich nicht alle emulierten Register in echten Registern behalten, weil Sie einige echte Register für etwas anderes in Ihrem Programm benötigen. –

Antwort

0

Soll der selbstmodifizierende Code verwendet werden? z.B. Setze die Registernummer in eine Anweisung, die gerade ausgeführt werden soll?

Das Problem ist mehr analog zu mehreren benannten Variablen in C (var1, var2, etc.) und den Wert in var i zurückgeben müssen. Sie können es mit dem Prä-Prozessor tun, wenn i eine Kompilierung-Konstante ist: (. Sprungtabelle, Zweig, oder was auch immer)

#define expandvar(x) var ## x // two step process to macro-expand x before concat 
#define var(x) expandvar(x) 
#define wantvar 4 

int foo(void) { return var(wantvar); } 
// int foo(constexpr int i) { ... } // nope 

Andernfalls müssen Sie eine switch(), die Sie jedoch implementieren können Sie

Es gibt keine Dereferenzierungsebene für Register, es sei denn, Sie speichern sie alle im Speicher und verwenden dann einen Variablenoffset für dieses Array.

Eine Möglichkeit, dies zu implementieren, ist mit einem berechneten Sprung, anstatt mit einer Tabelle von Sprungadressen. Sie müssten eine Folge von

# calculate $t0 = set_r0 + reg_num * 8. (probably using PC as the starting point, rather than actually referencing the address of set_r0) 
j $t0  # jump to one of the pairs. 

set_r0: 
    move $r0, src 
    j end 
    move $r1, src 
    j end 
    ... 

Wenn Sie den Wert eines Registers abgerufen werden wollte, aber alle anderen verprügeln,

move $r30, $r31 
    move $r29, $r30 
    move $r28, $r29 
    ... 
    move $r0, $r1 

Sprung in diese an dem Punkt, wo die reg Sie wollen, ist lesen.