Storing values in HI and LO registers of MIPS

32,130

Solution 1

I'd like to extend Nils Pipenbrinck answer:

From MIPS32 arquitechture for programmers

mthi

Format: MIPS32 (MIPS I)

  MTHI rs

Purpose: To copy a GPR to the special purpose HI register

Description: HI ← rs

The contents of GPR rs are loaded into special register HI.

Restrictions:

A computed result written to the HI/LO pair by DIV, DIVU,MULT, or MULTU must be read by MFHI or MFLO before a new result can be written into either HI or LO. If an MTHI instruction is executed following one of these arithmetic instructions, but before an MFLO or MFHI instruction, the contents of LO are UNPREDICTABLE. The following example shows this illegal situation:

 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

Historical Information:

In MIPS I-III, if either of the two preceding instructions is MFHI, the result of that MFHI is UNPREDICTABLE. Reads of the HI or LO special register must be separated from any subsequent instructions that write to them by two or more instructions. In MIPS IV and later, including MIPS32 and MIPS64, this restriction does not exist.

mtlo

Format: MIPS32 (MIPS I)

    MTLO rs

Purpose: To copy a GPR to the special purpose LO register Description:

 LO ← rs

The contents of GPR rs are loaded into special register LO.

Restrictions: A computed result written to the HI/LO pair by DIV, DIVU, MULT, or MULTU must be read by MFHI or MFLO before a new result can be written into either HI or LO.

If an MTLO instruction is executed following one of these arithmetic instructions, but before an MFLO or MFHI instruction, the contents of HI are UNPREDICTABLE. The following example shows this illegal situation:

 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

Historical Information:

In MIPS I-III, if either of the two preceding instructions is MFHI, the result of that MFHI is UNPREDICTABLE. Reads of the HI or LO special register must be separated from any subsequent instructions that write to them by two or more instructions. In MIPS IV and later, including MIPS32 and MIPS64, this restriction does not exist.

Solution 2

The MIPS instruction-set has a counterpart for MFLO/MFHI.

It's called MTLO/MTHI and does exactly what you want:

  mtlo $v0  # moves the contents of v0 into the lo-register
  mthi $v1  # moves the contents of v1 into the hi-register

These instructions are rare and often not present in summarized instruction set references.

Btw: Be sure to check the processor manual about the latencies and hazards involved with the LO/HI regs. They are very special and your code may have to things like waiting at least three cycles between a write and a read. Unfortunately this behaviour depends on which CPU you're working on.

Getting this wrong is a common pitfall for aspiring MIPS programmers :-)

Solution 3

Think about what other extreme values might produce interesting results when used as the second argument to multu/divu (I'm being intentionally vague because this looks like a homework question).

Share:
32,130
JxAxMxIxN
Author by

JxAxMxIxN

Updated on November 02, 2020

Comments

  • JxAxMxIxN
    JxAxMxIxN over 3 years

    I am writing certain code in MIPS and I've come to the point where the requirement is to store the result, temporarily, in HI and LO special registers (both are 4 bytes wide). These instructions are at my disposal:

    divu     s,t    lo <-- s div t ; hi <-- s mod t
    multu    s,t    hi / lo < -- s * t ;
    

    So, divu stores result of division in LO and remainder in HI, while multu stores result of multiplication in LO (lower 4 bytes) and HI (higher 4 bytes).

    Later, to retrieve result from HI and LO registers, I can:

    mfhi $v0
    mflo $v1
    

    I already figured out how to store result of a calculation in LO:

    ori     $v0,$0,1            # Store result from $a0 into LO
    divu    $a0,$v0
    
    • the divu stores result of the division in LO, so I just divide result by 1 to get it there.

    However, storing in HI is more complicated. One way would be to force multu instruction to shift the value by 32 bits (4 bytes):

    multu    $a0,0x80000000     # Shift $a0 by 32 bits and store into HI/LO
    

    But, the result is that the value in HI is 1 bit right of where it should be (so if my value is 0100 1000 then HI will contain 0010 0100).

    Does anyone know how to store something in HI register?

  • JxAxMxIxN
    JxAxMxIxN almost 15 years
    Thanks, this is indeed something I overlooked.
  • JxAxMxIxN
    JxAxMxIxN almost 15 years
    Don't think using multu and divu is possible to store values in HI/LO registers, since each instruction completely overwrites both registers unless great care is taken :( Damn MIPS.