【问题标题】:About negate a sign-integer in mips?关于否定 mips 中的符号整数?
【发布时间】:2019-05-03 06:04:12
【问题描述】:

我正在考虑如何否定 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 将尝试检测溢出,但这会使速度变慢吗?最后,有没有其他方法可以做到这一点?

【问题讨论】:

  • sub 变体更清晰;大家都知道0 - X == -X,但不是每个人都知道~X+1 == -X(也不是每个人都熟悉NOR运算)。它也尽可能快,因为它是一条指令。 nor / addiu 变体存在数据风险,其中addiu 取决于nor 指令的结果。在实践中,这可能会被处理而不会导致任何管道停顿,但这取决于您正在运行的特定 MIPS 实现。
  • sub 实际上做同样的事情,但在单个 ALU 操作中
  • @Michael:我也觉得sub更好,而且出现在我读的书中。但我只是好奇/怀疑底层正在做与我的第一个版本相同的事情......
  • @Minn:酷,你马上回答我的第二条评论。
  • 这两种变体并不等价。 sub 将导致算术溢出异常(即尝试计算 -INT_MIN 时)。如果你使用subu(或addi而不是addiu),它会是等价的。

标签: assembly mips cpu-architecture micro-optimization mips32


【解决方案1】:

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

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

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


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

On the Godbolt compiler explorer, 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 会尝试检测溢出,但这会使速度变慢吗?

没有。据我所知,在无异常情况下,sub 的性能与subu 相同。

CPU 针对常见情况进行了大量优化。在普通代码中很少发生异常,因此异常需要相当多的周期是可以的。因此,CPU 内核只需要在任何错误结果被写回寄存器文件或存储到缓存/内存之前检测到异常。在任何 MIPS 管道上,执行和回写之间至少有几个管道阶段。

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

【讨论】:

  • 请注意,有符号溢出是未定义的行为在 C 中(例如,如果编译器愿意,可以使用 sub,或者假设 @987654337 @result 没有溢出到 INT_MIN,因此之前和之后的 x 不可能是 INT_MIN)。因此,如果您在查找绝对值的过程中执行此操作,您需要避免在进行无符号减法之前使用0U - xx 转换为unsigned,从而产生无符号结果。在像 MIPS 这样的 2 的补码机器上,将有符号 int 转换为相同宽度的无符号是免费的,只需使用未更改的位模式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 2011-09-03
  • 1970-01-01
  • 2013-02-26
相关资源
最近更新 更多