Почему в MIPS есть два способа умножения произвольных чисел со знаком? - PullRequest
0 голосов
/ 10 октября 2018

Если вам нужно умножить два произвольных числа со знаком в MIPS, есть ли причина предпочитать:

mul $t0 $s0 $s1

Или это:

mult $s0 $s1
mflo $t0

?

Я нахожу противоречивые ответы онлайн в отношении того, что каждый из них означает.На первый взгляд, я ожидаю, что первое будет псевдоинструкцией для второго.(И даже есть веб-страница, которая утверждает, что.) Но, глядя на машинный код, кажется, что mult является действительной инструкцией R-типа (код операции 0), тогда как mul имеет ненулевой код операции (0x1c) и поэтому не должен 'не может быть R-типа, даже если он содержит 3 регистра?Но я просто не думаю о том, почему вам нужно два разных способа размножения.Оба влияют на lo и hi (используя MARS), поэтому вы можете проверить переполнение с помощью любого из них.Так почему избыточность?Почему бы просто не сказать всем использовать mul все время?

1 Ответ

0 голосов
/ 11 октября 2018

mul - это , а не - псевдоинструкция.Он не изменяет регистры hi или lo, которые mult делает.Это разные действительные инструкции в наборе команд.

В общем, мы имеем a = b * c

Поскольку умножение двух 32-битных чисел вместе дает 64-битный результат, вв общем случае мы используем mult, а затем получаем младшие 32 бита результата с mflo и старшие 32 бита с mfhi.Это позволяет повысить точность за счет необходимости в дополнительной инструкции [или двух] для получения результата.

Если мы заботимся только о младших 32 битах результата умножения (например, вычисления индекса массива), мыможно использовать mul, что позволяет результату находиться в регистре, отличном от аргументов (в одиночной инструкции)

Рассмотрим простую программу:

    .text
    .globl  main
main:
    mul     $v0,$a0,$a1
    mult    $v1,$a2
    mflo    $v0

Теперь, если мы соберем его, используя mars, мы получим:

00400000:   70851002    mul     $v0,$a0,$a1
00400004:   00660018    mult    $v1,$a2
00400008:   00001012    mflo    $v0

Обратите внимание, что у нас есть настоящая инструкция mflo в строке 3. Если mul были псевдо-оп, mars [пришлось бы] ввести mflo $v0 между mul и mult строками


ОБНОВЛЕНИЕ:

Это интересно.И вы правы, что это не псевдоинструкция.(Вы увидите это, когда он будет собран, если он будет.) Но когда я использую MARS, и mul, и mult изменяют hi и lo.Может быть, это ошибка MARS?

Возможно.spim также изменяет hi и lo.

При дальнейшем размышлении это кажется логичным, учитывая эпоху оригинальных ядер CPU mips (около 1985 г.) и [чрезвычайно] ограниченное количество вентилейони имели.

Но настоящие мипс-ядра все еще живы сегодня.Компания является "MIPS Technologies, Inc", и она все еще существует с 2017 года.

Справочное руководство ISA от компании [AFAICT] имеет копию здесь: https://s3 -eu-west-1.amazonaws.com / downloads-mips / documents / MD00086-2B-MIPS32BIS-AFP-6.06.pdf

В этом документе инструкция mul делает не изменение спискаПривет или Ло как побочный эффект.

В каком-то документе, который я видел [я не могу вспомнить, какой], в нем говорится [для старого / реального оборудования], что вы должны иметьпромежуточная инструкция между mult и mflo (например, nop).Симуляторы не требуют этого.

Как хорошая практика, я, вероятно, не стал бы полагать, что lo / hi действителен слишком долго после того, как mult и не полагаются на них вообщедля mul, так что для классной работы это немного спорный вопрос.

Было бы интересно посмотреть, что делает qemu.Его сложнее использовать, чем spim или mars [который я предпочитаю], но может быть ближе к тому, что делает настоящее оборудование.

...