关于否定mips中的符号整数? [英] About negate a sign-integer in mips?

查看:45
本文介绍了关于否定mips中的符号整数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在考虑如何对mips32中的带符号整数取反.我的直觉是使用2的补码的定义,例如:(假设 $ s0 是要取反的数字)

I'm thinking about how to negate a signed-integer in mips32. My intuition is using definition of 2's complement like: (suppose $s0 is the number to be negated)

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

然后我意识到可以这样做:

then I realized that it can be done like:

sub $t0, $zero, $s0

所以...有什么区别?哪个更快?IIRC子程序将尝试检测溢出,但这会使速度变慢吗?最后,还有其他方法吗?

so... what's the difference? Which is faster? IIRC sub will try to detect overflow, but would this make is slower? Finally, is there any other way to do so?

推荐答案

subu $ t0,$ zero,$ s0 是最好的方法,也是编译器的作用.

subu $t0, $zero, $s0 is the best way, and is what compilers do.

在任何给定的MIPS实现上,大多数简单的ALU指令(加/减/和/减)具有相同的性能.用一条简单的指令而不是两条简单的指令完成相同的工作是代码大小,延迟和吞吐量的胜利.

On any given implementation of MIPS, most simple ALU instructions (add/sub/and/nor) have identical performance. Getting the same work done in 1 simple instruction instead of 2 simple instructions is a win for code-size, latency, and throughput.

更少的指令并不总是更好,但是作为经典的RISC ISA的MIPS除了mult/div/rem之外没有很多慢"指令.

Fewer instructions isn't always better, but MIPS being a classic RISC ISA doesn't have many "slow" instructions other than mult / div / rem.

sub 而不是 subu 会在 -INT_MIN 上引发异常,避免在该代码中使用 addiu 也不/添加版本.您应该始终使用 sub add 指令的 u 版本,除非您特别想要签名溢出引发异常.C编译器始终使用 u 版本.(在C语言中,带符号的溢出是未定义的行为.这意味着它允许出错,但不是必需的出错,并且通常没人希望这样做.编译器希望能够优化和引入可创建临时值的转换C抽象机中从未存在过,因此这样做必须避免出错.)

sub instead of subu would raise an exception on -INT_MIN, which you avoid using addiu in the nor/add version. You should always use the u version of sub and add instructions unless you specifically want signed overflow to raise an exception. C compilers always use the u version. (In C, signed overflow is undefined behaviour. That means it's allowed to fault, but not required to fault, and generally nobody wants that. Compilers want to be able to optimize and introduce transformations that create temporary values that never exist in the C abstract machine, so they must avoid faulting when doing that.)

在Godbolt编译器资源管理器上, MIPS gcc5.4 -O3编译

On the Godbolt compiler explorer, MIPS gcc5.4 -O3 compiles

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

进入

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

完全符合我们的预期.询问编译器通常是找到在asm中执行操作的有效方法的好方法.

exactly like we'd expect. Asking a compiler is usually a good way to find efficient ways to do things in asm.

IIRC子程序将尝试检测溢出,但这会使速度变慢吗?

IIRC sub will try to detect overflow, but would this make is slower?

不.据我所知,在无例外情况下, sub 具有与 subu 相同的性能.

No. In the no-exception case, sub has the same performance as subu, as far as I know.

CPU针对常见情况进行了优化.接受异常的情况在普通代码中很少发生,以至于例外需要花费很多时间.因此,CPU内核只需在将任何不良结果写回到寄存器文件或存储到缓存/内存中之前检测到异常.在任何MIPS管道上,执行"和写回"之间至少有几个管道阶段.

CPUs are heavily optimized for the common case. Taking an exception happens so rarely in normal code that it's fine for exceptions to take quite a lot of cycles. So the CPU core just has to detect an exception before any bad result is written back to the register file, or stored to cache/memory. There are at least a couple pipeline stages between Execute and Write-Back on any MIPS pipeline.

在有符号溢出的情况下,ALU可以在与结果相同的周期内产生溢出信号.(具有大多数指令更新的带有标志"寄存器的ISA一直在 add 指令的常规操作中始终执行此操作:如果软件想对x86或ARM上的带符号溢出进行特殊处理,,他们会在溢出标志上使用条件分支(x86上的OF,ARM上的V).MIPS的特殊之处在于,除了对有符号的溢出采取例外处理之外,很难做其他任何事情.)

In the case of signed overflow, the ALU can produce the overflow signal in the same cycle as the result. (ISAs with a "flags" register that's updated by most instructions do this all the time as part of the normal operation of an add instruction: if software wants to do something special on signed overflow on x86 or ARM, they'd use a conditional branch on the overflow flag (OF on x86, V on ARM). MIPS is special in that it's difficult to do anything other than take an exception on signed overflow.)

这篇关于关于否定mips中的符号整数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆