Сохранение значений в регистрах HI и LO MIPS

Я пишу определенный код в MIPS, и я пришел к тому, что требуется временно сохранить результат в специальных регистрах HI и LO (оба имеют ширину 4 байта). Эти инструкции в моем распоряжении:

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

Итак, divu хранит результат деления в LO и остаток в HI, а multu хранит результат умножения в LO (младшие 4 байта) и HI (старшие 4 байта).

Позже, чтобы получить результат из регистров HI и LO, я могу:

mfhi $v0
mflo $v1

Я уже понял, как сохранить результат вычисления в LO:

ori     $v0,$0,1            # Store result from $a0 into LO
divu    $a0,$v0
  • divu хранит результат деления в LO, поэтому я просто делю результат на 1, чтобы получить его там.

Однако хранить в HI сложнее. Один из способов — заставить инструкцию multu сдвинуть значение на 32 бита (4 байта):

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

Но в результате значение в HI находится на 1 бит справа от того места, где оно должно быть (поэтому, если мое значение равно 0100 1000, то HI будет содержать 0010 0100).

Кто-нибудь знает, как хранить что-то в регистре HI?


person DV.    schedule 05.05.2009    source источник
comment
32 бита (8 байтов). эээ, 32b - это 4 байта, а не 8. в 32-битном MIPS каждый HI и LO - 4 байта. Это 64-битная конкатенация пары из 8 байтов (которая не помещается ни в один регистр).   -  person Peter Cordes    schedule 02.11.2016


Ответы (3)


Я хотел бы расширить ответ Нильса Пипенбринка:

От архитектуры MIPS32 для программистов

мти

Формат: MIPS32 (MIPS I)

  MTHI rs

Цель: скопировать GPR в специальный регистр HI.

Description: HI ← rs

Содержимое GPR rs загружается в специальный регистр HI.

Ограничения:

Вычисленный результат, записанный в пару HI/LO с помощью DIV, DIVU,MULT или MULTU, должен быть прочитан с помощью MFHI или MFLO, прежде чем новый результат можно будет записать в HI или LO. Если инструкция MTHI выполняется после одной из этих арифметических инструкций, но до инструкции MFLO или MFHI, содержимое LO НЕПРЕДСКАЗУЕМО. В следующем примере показана эта недопустимая ситуация:

 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

Историческая информация:

В MIPS I-III, если любая из двух предыдущих инструкций является MFHI, результат этой MFHI НЕПРЕДСКАЗУЕМ. Чтения специального регистра HI или LO должны быть отделены от любых последующих инструкций, выполняющих запись в них, двумя или более инструкциями. В MIPS IV и более поздних версиях, включая MIPS32 и MIPS64, этого ограничения не существует.

мтло

Формат: MIPS32 (MIPS I)

    MTLO rs

Назначение: скопировать GPR в специальный регистр LO. Описание:

 LO ← rs

Содержимое GPR rs загружается в специальный регистр LO.

Ограничения: Вычисленный результат, записанный в пару HI/LO с помощью DIV, DIVU, MULT или MULTU, должен быть прочитан с помощью MFHI или MFLO, прежде чем новый результат можно будет записать в HI или LO.

Если инструкция MTLO выполняется после одной из этих арифметических инструкций, но до инструкции MFLO или MFHI, содержимое HI НЕПРЕДСКАЗУЕМО. В следующем примере показана эта недопустимая ситуация:

 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

Историческая информация:

В MIPS I-III, если любая из двух предыдущих инструкций является MFHI, результат этой MFHI НЕПРЕДСКАЗУЕМ. Чтения специального регистра HI или LO должны быть отделены от любых последующих инструкций, выполняющих запись в них, двумя или более инструкциями. В MIPS IV и более поздних версиях, включая MIPS32 и MIPS64, этого ограничения не существует.

person Tom    schedule 05.05.2009

Набор инструкций MIPS имеет аналог для MFLO/MFHI.

Он называется MTLO/MTHI и делает именно то, что вам нужно:

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

Эти инструкции встречаются редко и часто отсутствуют в сводных справочниках по наборам инструкций.

Кстати: обязательно ознакомьтесь с руководством по процессору о задержках и опасностях, связанных с регистрами LO/HI. Они очень особенные, и ваш код может иметь такие вещи, как ожидание по крайней мере трех циклов между записью и чтением. К сожалению, это поведение зависит от того, на каком процессоре вы работаете.

Неправильное понимание этого является распространенной ошибкой для начинающих программистов MIPS :-)

person Nils Pipenbrinck    schedule 05.05.2009
comment
Спасибо, это действительно то, что я упустил из виду. - person DV.; 06.05.2009

Подумайте о том, какие другие экстремальные значения могут дать интересные результаты при использовании в качестве второго аргумента для multu/divu (я намеренно расплывчат, потому что это похоже на вопрос домашнего задания).

person outis    schedule 05.05.2009
comment
Не думайте, что использование multu и divu возможно для хранения значений в регистрах HI/LO, поскольку каждая инструкция полностью перезаписывает оба регистра, если не соблюдать осторожность :( Проклятый MIPS. - person DV.; 07.05.2009