assembly - 零/符号扩展是空操作,那么为什么要对每种尺寸类型进行说明呢?

标签 assembly riscv sign-extension zero-extension

对于 x86 和 x64 编译器生成类似的零/符号扩展 MOVSX 和 MOVZX。扩展本身不是免费的,但允许处理器执行乱序魔法加速。

但是在 RISC-V 上:

Consequently, conversion between unsigned and signed 32-bit integers is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.

A few new instructions (ADD[I]W/SUBW/SxxW) are required for addition and shifts to ensure reasonable performance for 32-bit values.

(C) RISC-V Spec

但与此同时,新的现代 RISC-V 64 位处理器包含用于 32 位有符号整数的指令。为什么?为了提高性能?那么 8 位和 16 位在哪里?我已经什么都不懂了。

最佳答案

完整的引用对我来说似乎很清楚:

The compiler and calling convention maintain an invariant that all 32-bit values are held in a sign-extended format in 64-bit registers. Even 32-bit unsigned integers extend bit 31 into bits 63 through 32.

Consequently, conversion between unsigned and signed 32-bit integers is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.
Existing 64-bit wide SLTU and unsigned branch compares still operate correctly on unsigned 32-bit integers under this invariant.
Similarly, existing 64-bit wide logical operations on 32-bit sign-extended integers preserve the sign-extension property.

A few new instructions (ADD[I]W/SUBW/SxxW) are required for addition and shifts to ensure reasonable performance for 32-bit values.

它表示 32 位值存储在 64 位寄存器中,其 MSb(最高有效位)重复第 32-63 位。
这是针对 有符号和无符号 整数完成的。

这允许进行一些优化,如引述中所述:

  • Unsigned <-> signed 转换是免费的。
    将此与您必须将低 32 位值归零或符号扩展以将其提升为不同“符号”的 64 位值(忽略溢出)的常用算法进行比较。
  • 带符号的 32 位 <-> 带符号的 64 位是免费的。
    这节省了符号扩展。
  • 分支和设置指令仍然有效。
    这是因为重复 MSb 不会改变比较结果。
  • 逻辑 64 位操作保留此属性
    通过几个例子很容易看出这一点。

然而,加法(举一个例子)并没有保留这个不变量:0x000000007fffffff + 0x0000000000000001 = 0x0000000080000000,这违反了假设。

因为 a) 使用 32 位值经常发生并且 b) 修复结果需要额外的工作(我可以考虑使用 slli/srai 对) 引入了一种新的指令格式。
这些指令对 64 位寄存器进行操作,但仅使用其较低的 32 位值并将对 32 位结果进行符号扩展。
这在硬件中很容易完成,因此拥有这种新的指令类是值得的。

如评论中所述,8 位和 16 位算术很少见,因此没有花费任何工程努力为其寻找新空间(无论是在所需的门还是使用的操作码空间方面)。

关于assembly - 零/符号扩展是空操作,那么为什么要对每种尺寸类型进行说明呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52646216/

相关文章:

assembly - 为什么 2 的补码符号扩展通过添加符号位的副本来工作?

c - 符号扩展的必要性是什么?

gcc - 支持矢量的 RISC-V 工具链

caching - RISC-V Rocket 缓存一致性

c - 热补丁填充始终是 16 的倍数吗?

visual-studio - Microsoft 汇编程序到 GNU 汇编程序的转换

c - 如何制作一个简单的多核多线程裸机程序?

assembly - 我们何时以及为何签署扩展并使用带有 mul/div 的 cdq?

gcc - 基于 x86-64 汇编的索引寻址和段错误

c++ - 堆栈上的 G++ SSE 内存对齐