Memorizzazione dei valori nei registri HI e LO dei MIPS
-
05-07-2019 - |
Domanda
Sto scrivendo un determinato codice in MIPS e sono arrivato al punto in cui l'obbligo è di memorizzare temporaneamente il risultato nei registri speciali HI
e LO
( entrambi hanno una larghezza di 4 byte). Queste istruzioni sono a mia disposizione:
divu s,t lo <-- s div t ; hi <-- s mod t
multu s,t hi / lo < -- s * t ;
Quindi, divu
memorizza il risultato della divisione in LO
e il resto in HI
, mentre multu
memorizza il risultato di moltiplicazione in LO
(4 byte inferiori) e HI
(4 byte superiori).
In seguito, per recuperare il risultato dai registri HI
e LO
, posso:
mfhi $v0
mflo $v1
Ho già capito come memorizzare il risultato di un calcolo in LO
:
ori $v0,multu $a0,0x80000000 # Shift $a0 by 32 bits and store into HI/LO
,1 # Store result from $a0 into LO
divu $a0,$v0
-
divu
memorizza il risultato della divisione in LO, quindi divido il risultato per 1 per ottenerlo.
Tuttavia, la memorizzazione in HI
è più complicata. Un modo sarebbe forzare l'istruzione multu
per spostare il valore di 32 bit (4 byte):
Ma il risultato è che il valore in HI
è 1 bit a destra di dove dovrebbe essere (quindi se il mio valore è 0100 1000
quindi HI
conterrà 0010 0100
).
Qualcuno sa come archiviare qualcosa nel registro HI
?
Soluzione
Vorrei estendere la risposta di Nils Pipenbrinck:
Da MIPS32 arquitechture per programmatori
MThI
Formato: MIPS32 (MIPS I)
MTHI rs
Scopo: Per copiare un GPR nello speciale registro HI
Description: HI ← rs
I contenuti di GPR rs vengono caricati nel registro speciale HI.
Restrizioni:
Un risultato calcolato scritto sulla coppia HI / LO da DIV, DIVU, MULT o MULTU deve essere letto da MFHI o MFLO prima che un nuovo risultato possa essere scritto in HI o LO. Se un'istruzione MTHI viene eseguita seguendo una di queste istruzioni aritmetiche, ma prima di un MFLO o MFHI istruzione, il contenuto di LO è INCREDIBILE. L'esempio seguente mostra questa situazione illegale:
MUL r2,r4 # start operation that will eventually write to HI,LO
... # code not containing mfhi or mflo
MTHI r6
... # code not containing mflo
# this mflo would get an UNPREDICTABLE value
MFLO r3
Informazioni storiche:
In MIPS I-III, se una delle due istruzioni precedenti è MFHI, il risultato di tale MFHI è IMPREVEDIBILE. Le letture del registro speciale HI o LO devono essere separate dalle istruzioni successive che le scrivono in due o più istruzioni. In MIPS IV e versioni successive, inclusi MIPS32 e MIPS64, questa restrizione non esiste.
mtlo
Formato: MIPS32 (MIPS I)
MTLO rs
Scopo: Per copiare un GPR nel registro LO per scopi speciali Descrizione:
LO ← rs
Il contenuto di GPR rs viene caricato nel registro speciale LO.
Restrizioni: Un risultato calcolato scritto sulla coppia HI / LO da DIV, DIVU, MULT o MULTU deve essere letto da MFHI o MFLO prima di poter scrivere un nuovo risultato in HI o LO.
Se un'istruzione MTLO viene eseguita seguendo una di queste istruzioni aritmetiche, ma prima di un'istruzione MFLO o MFHI, il contenuto di HI è INCREDIBILE. L'esempio seguente mostra questa situazione illegale:
MUL r2,r4 # start operation that will eventually write to HI,LO
... # code not containing mfhi or mflo
MTLO r6
... # code not containing mfhi
# this mfhi would get an UNPREDICTABLE value
MFHI r3
Informazioni storiche:
In MIPS I-III, se una delle due istruzioni precedenti è MFHI, il risultato di tale MFHI è IMPREVEDIBILE. Le letture del registro speciale HI o LO devono essere separate dalle istruzioni successive che le scrivono in due o più istruzioni. In MIPS IV e versioni successive, inclusi MIPS32 e MIPS64, questa restrizione non esiste.
Altri suggerimenti
Il set di istruzioni MIPS ha una controparte per MFLO / MFHI.
Si chiama MTLO / MTHI e fa esattamente quello che vuoi:
mtlo $v0 # moves the contents of v0 into the lo-register
mthi $v1 # moves the contents of v1 into the hi-register
Queste istruzioni sono rare e spesso non sono presenti nei riferimenti sintetici del set di istruzioni.
Btw: assicurati di controllare il manuale del processore per quanto riguarda le latenze e i rischi associati ai registri LO / HI. Sono molto speciali e il tuo codice potrebbe dover fare cose come aspettare almeno tre cicli tra una scrittura e una lettura. Sfortunatamente questo comportamento dipende dalla CPU su cui stai lavorando.
Sbagliare è una trappola comune per aspiranti programmatori MIPS :-)
Pensa a quali altri valori estremi potrebbero produrre risultati interessanti se usato come secondo argomento di multu / divu (sono intenzionalmente vago perché sembra una domanda a casa).