О отрицании знака-целого числа в мипс? - PullRequest
0 голосов
/ 01 декабря 2018

Я думаю о том, как отрицать целое число со знаком в mips32.Моя интуиция использует определение дополнения 2, например: (предположим, $s0 - это число, которое нужно отрицать)

nor $t0, $s0, $s0   ; 1's complement
addiu $t0, $t0, 1   ; 2's = 1's + 1

, тогда я понял, что это можно сделать так:

sub $t0, $zero, $s0

так ... какая разница?Что быстрее?IIRC sub попытается обнаружить переполнение, но будет ли это медленнее?Наконец, есть ли другой способ сделать это?

1 Ответ

0 голосов
/ 01 декабря 2018

subu $t0, $zero, $s0 - лучший способ, и именно это делают компиляторы.

В любой конкретной реализации MIPS большинство простых инструкций ALU (add / sub / и / nor) имеют одинаковую производительность.Выполнение той же работы в 1 простой инструкции вместо 2 простых инструкций - это выигрыш в размере кода, задержке и пропускной способности.

Меньше инструкций не всегда лучше, но MIPSклассический RISC ISA не имеет много «медленных» инструкций, кроме mult / div / rem.


sub вместо subu вызовет исключение для -INT_MIN, которого вы избегаетеиспользуя addiu в версии nor / add.Вы всегда должны использовать u версию инструкций sub и add, если только вы специально не хотите переполнение со знаком для создания исключения.Компиляторы C всегда используют версию u.(В C переполнение со знаком является неопределенным поведением. Это означает, что допускается ошибка, но не требуется требуется ошибки, и, как правило, этого никто не хочет. Компиляторы хотят иметь возможность оптимизировать и вводить преобразования, которые создают временные значения, которыеникогда не существует в абстрактной машине C, поэтому они должны избегать ошибок при этом.)

В проводнике компилятора Godbolt, MIPS gcc5.4 -O3 компилирует

int neg(int x) { return -x; }

в

neg(int):
    j       $31
    subu    $2,$0,$4        # in the branch delay slot

точно так, как мы ожидали.Запрашиваемая компилятором, как правило, является хорошим способом найти эффективные способы сделать что-то в asm.


Сабвуфер IIRC попытается обнаружить переполнение, но будет ли это медленнее?*

Нет.Насколько я знаю, в случае без исключений sub имеет ту же производительность, что и subu.

Процессоры сильно оптимизированы для общего случая.Принятие исключения происходит в обычном коде настолько редко, что для исключений достаточно много циклов.Таким образом, ядро ​​ЦП просто должно обнаружить исключение, прежде чем какой-либо неверный результат будет записан обратно в файл реестра или сохранен в кэш / память.В любом конвейере MIPS существует как минимум пара каскадов конвейера между исполнением и обратной записью.

В случае переполнения со знаком ALU может генерировать сигнал переполнения в том же цикле, что и результат.(ISA с регистром «flags», который обновляется большинством инструкций, делают это все время как часть нормальной операции инструкции add: если программное обеспечение хочет сделать что-то особенное при переполнении со знаком на x86 или ARM, они используютусловная ветвь на флаге переполнения (OF на x86, V на ARM). MIPS отличается тем, что трудно что-либо сделать, кроме как сделать исключение при подписанном переполнении.)

...