Almacenamiento de valores en registros HI y LO de MIPS
-
05-07-2019 - |
Pregunta
Estoy escribiendo cierto código en MIPS y he llegado al punto donde el requisito es almacenar el resultado, temporalmente, en los registros especiales HI
y LO
( ambos tienen 4 bytes de ancho). Estas instrucciones están a mi disposición:
divu s,t lo <-- s div t ; hi <-- s mod t
multu s,t hi / lo < -- s * t ;
Entonces, divu
almacena el resultado de la división en LO
y el resto en HI
, mientras que multu
almacena el resultado de multiplicación en LO
(4 bytes inferiores) y HI
(4 bytes superiores).
Más tarde, para recuperar el resultado de los registros HI
y LO
, puedo:
mfhi $v0
mflo $v1
Ya descubrí cómo almacenar el resultado de un cálculo en 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
- el
divu
almacena el resultado de la división en LO, así que simplemente divido el resultado entre 1 para obtenerlo allí.
Sin embargo, almacenar en HI
es más complicado. Una forma sería forzar la instrucción multu
para cambiar el valor en 32 bits (4 bytes):
Pero, el resultado es que el valor en HI
está 1 bit a la derecha de donde debería estar (así que si mi valor es 0100 1000
entonces HI
contendrá 0010 0100
).
¿Alguien sabe cómo almacenar algo en el registro HI
?
Solución
Me gustaría extender la respuesta de Nils Pipenbrinck:
De la arquitectura MIPS32 para programadores
mthi
Formato: MIPS32 (MIPS I)
MTHI rs
Propósito: Para copiar un GPR al registro HI de propósito especial
Description: HI ← rs
El contenido de GPR rs se carga en el registro especial HI.
Restricciones:
Un resultado calculado escrito en el par HI / LO por DIV, DIVU, MULT o MULTU debe ser leído por MFHI o MFLO antes de que se pueda escribir un nuevo resultado en HI o LO. Si se ejecuta una instrucción MTHI siguiendo una de estas instrucciones aritméticas, pero antes de un MFLO o MFHI instrucción, los contenidos de LO son IMPRIMIBLES. El siguiente ejemplo muestra esta situación ilegal:
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
Información histórica:
En MIPS I-III, si cualquiera de las dos instrucciones anteriores es MFHI, el resultado de esa MFHI es IMPREDECIBLE. Las lecturas del registro especial HI o LO deben estar separadas de cualquier instrucción posterior que les escriba por dos o más instrucciones En MIPS IV y posterior, incluidos MIPS32 y MIPS64, esta restricción no existe.
mtlo
Formato: MIPS32 (MIPS I)
MTLO rs
Propósito: Para copiar un GPR al registro LO de propósito especial Descripción:
LO ← rs
El contenido de GPR rs se carga en el registro especial LO.
Restricciones: MFHI o MFLO debe leer un resultado calculado escrito en el par HI / LO por DIV, DIVU, MULT o MULTU antes de que un nuevo resultado pueda escribirse en HI o LO.
Si una instrucción MTLO se ejecuta siguiendo una de estas instrucciones aritméticas, pero antes de una instrucción MFLO o MFHI, el contenido de HI es IMPREDECIBLE. El siguiente ejemplo muestra esta situación ilegal:
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
Información histórica:
En MIPS I-III, si cualquiera de las dos instrucciones anteriores es MFHI, el resultado de esa MFHI es IMPREDECIBLE. Las lecturas del registro especial HI o LO deben estar separadas de cualquier instrucción posterior que les escriba por dos o más instrucciones En MIPS IV y posterior, incluidos MIPS32 y MIPS64, esta restricción no existe.
Otros consejos
El conjunto de instrucciones MIPS tiene una contraparte para MFLO / MFHI.
Se llama MTLO / MTHI y hace exactamente lo que quieres:
mtlo $v0 # moves the contents of v0 into the lo-register
mthi $v1 # moves the contents of v1 into the hi-register
Estas instrucciones son raras y a menudo no están presentes en las referencias resumidas del conjunto de instrucciones.
Por cierto: asegúrese de consultar el manual del procesador sobre las latencias y los riesgos relacionados con los registros LO / HI. Son muy especiales y su código puede tener que esperar al menos tres ciclos entre una escritura y una lectura. Lamentablemente, este comportamiento depende de la CPU en la que esté trabajando.
Hacer esto mal es una trampa común para los aspirantes a programadores de MIPS :-)
Piense en qué otros valores extremos podrían producir resultados interesantes cuando se usa como segundo argumento para multu / divu (estoy siendo intencionalmente vago porque esto parece una pregunta de tarea).