gpt4 book ai didi

assembly - 关于否定 mips 中的符号整数?

转载 作者:行者123 更新时间:2023-12-02 00:26:45 24 4
gpt4 key购买 nike

我正在考虑如何取反 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 将尝试检测溢出,但这会使速度变慢吗?最后,还有其他方法吗?

最佳答案

subu $t0, $zero, $s0是最好的方式,也是编译器所做的。

在任何给定的 MIPS 实现中,大多数简单的 ALU 指令(add/sub/and/nor)具有相同的性能。用 1 条简单指令而不是 2 条简单指令完成相同的工作是代码大小、延迟和吞吐量的胜利。

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

如果你想要-x-1然后您将其优化为单个 nor $t0, $zero, $s0使用 a 2's complement identity .


sub而不是 subu会在 -INT_MIN 上引发异常,你避免使用 addiu在 nor/add 版本中。您应该始终使用 u sub 的版本和 add说明,除非您特别想要签名溢出以引发异常。 C 编译器总是使用 u版本。 (在 C 中,有符号溢出是未定义的行为1。)

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

On the Godbolt compiler explorer , MIPS gcc11.2 -O3 -fno-delayed-branch完全按照我们的预期编译它:

neg(int):
subu $2,$0,$4
jr $31
nop # filling the branch delay slot for

询问编译器通常是找到在 asm 中做事的有效方法的好方法。 (GCC 始终使 asm 与真正的 MIPS CPU 兼容,而 GAS 不同于 MARS/SPIM 经典 MIPS 汇编器。另请参见 Tweak mips-gcc output to work with MARS)


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

没有。在无一异常(exception)的情况下,sub具有与 subu 相同的性能,据我所知在所有 MIPS CPU 上。

CPU 针对常见情况进行了大量优化。在正常代码中很少发生异常(exception)情况,因此异常(exception)情况需要相当多的周期。因此,CPU 内核只需在将任何不良结果写回寄存器文件或存储到缓存/内存之前检测到异常。在任何 MIPS 流水线的执行和回写之间至少有几个流水线阶段。

在有符号溢出的情况下,ALU 可以在与结果相同的周期内产生溢出信号。带有被大多数指令更新的“标志”寄存器的 ISA 作为 add 的正常操作的一部分一直这样做。指令:如果软件想在 x86 或 ARM 上对有符号溢出做一些特殊的事情,他们会在溢出标志上使用条件分支(x86 上为 OF,ARM 上为 V)。 MIPS 的特殊之处在于,除了对有符号溢出采取异常之外,很难做任何事情。


脚注 1: 未定义行为意味着它可以出错,但不是必须出错,而且通常人们希望它没有。编译器希望能够优化和引入创建 C 抽象机中永远不存在的临时值的转换,因此他们必须避免在这样做时出错。始终使用 subu是一个很好的方法,因此它不需要跟踪操作和输入值是否是 C 抽象机中会发生的值。但在这种情况下,使用 sub 是合法的.

UB 的另一个含义是允许编译器假定 -x结果没有溢出到INT_MIN因此 x之前和之后不可能是INT_MIN .

因此,如果您将此作为查找绝对值的一部分,则需要使用 0U - x 来避免这种情况。转换 x在进行无符号减法之前变为无符号,产生无符号结果。在像 MIPS 这样的 2 的补码机器上,将 signed int 强制转换为相同宽度的 unsigned 是免费的,只需使用不变的位模式即可。 return x<0 ? 0U - x : x;

为此,2 的补码比特黑客很有用,GCC 将其与-march=mips32r3 一起使用。然后。 (IDK 为什么它认为分支在像 -march=r14000 这样的 CPU 上更好,一个 4-wide out-of-order exec CPU。)

uabs(int):
sra $3,$4,31 # broadcast the sign bit
xor $2,$4,$3 # ~x or x
subu $2,$2,$3 # ~x-(-1) or x
jr $31
nop

关于assembly - 关于否定 mips 中的符号整数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53568440/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com