为什么RISC-V没有计算执行指令?

pie*_*mes 10 assembly instruction-set bignum riscv

我需要在RISC-V上处理bignum计算(加法和减法,但我将减法视为等同于有符号加法),情况有点复杂。我通过半个小时的互联网研究得到的信息:

  • RISC-V 操作不提供检查进位或溢出的方法
  • 这一决定的动机是,标志或其他处理方法给无序微架构增加了很多复杂性。
  • 相反,他们建议事后进行分支
    • 对于无符号加法,可以使用单个bltu.
    • 如果操作数之一的符号已知,则与有符号加法相同
    • 否则,需要执行两次检查(三个附加指令)
  • 互联网上的人们对此非常愤怒(我不会在这里链接)

据我所知,这些分支确实很好地涵盖了大多数场景,除了一个:(有符号)bignum 加法。因为在那里,我们遇到了热循环中最慢的检查路径。

我对 ISA 设计知之甚少,但为什么他们不包含计算(a + b) >> 32(实际上是执行)的指令?有点像乘法指令被分成mulmulh的方式。这将允许始终使用两条指令进行所需的计算。更强大的微架构甚至可以检测序列并且只进行一项加法。

我是否遗漏了一些会使该指令过时(或与其等效)的技巧?它有我需要监督的重大缺点吗?我没有找到关于这个一般主题的很多好的文档。

Pet*_*des 9

add/sltu为您提供求和和进位:https://godbolt.org/z/Y7f5dzj1P显示 GCC 使用它进行无符号数学:sum=a+b/ carry = sum<a。或者为了__builtin_uadd_overflow

\n

但问题是缺乏 ILP:在结果准备好sltu之前无法启动。add如果您可以按照您的建议直接从输入中获取结转,则可以解决这个问题;好点子。当然add/sltu的融合也能解决这个问题;也许这就是建筑师的想法。

\n

在创建根据 2 输入加法的进位输出生成 a0或输出的指令时,我没有看到任何 CPU 设计挑战。1那会很容易;任何构建 32 位或 64 位加法器来支持add指令的方法都可以轻松地从高位产生进位信号。事实上,这可能就是读到的内容,因为整数 ALU 使用单个二进制加减器sltu是正常的,其中一个输入的 NOT 和一个进位来实现减法。(低位是全加器而不是半加器,否则是普通的二进制加法器。)1

\n
\n

超过 2 个寄存器宽度的 bignum 的另一个主要问题是进行进位加法在具有进位标志和进位加法指令的 ISA 上)。

\n

更糟糕的是,从 3 输入加法中获取进位。(其中的任何一部分都可以换行,因此不可能将其组合成一个添加和比较。这是纯 C 实现的常见陷阱adc;对该链接答案的注释具有有效的 C,但它没有\编译效率不高)。

\n

除非有什么我不知道的技巧,否则我认为这才是真正让人们对无标志设计(例如用于 Bignum 的 RISC-V 和 MIPS)感到不安的原因。

\n

更新:\xc5\x98r\xc5\x99ola\ 的答案add/adc/adc/adc显示纯 C,clang 将使用 add-with-carry 指令编译为 x86-64 或其他 ISA 的链。对于 RV64 ( https://godbolt.org/z/oaevGs67q ),看起来我们为每个同时具有进位和进位的加法步骤获得 2xsltu和 3x 。add我不知道这是否是最佳的;clang 目前只支持_BitInt(128)RV64,我没有检查https://gmplib.org/ mpn手写的 asm。

\n

  • 这对于尝试进行椭圆曲线加密实现的密码学家来说也非常糟糕——加法/乘法后的分支会阻止代码保持恒定时间,并可能通过侧通道泄露信息。 (2认同)