对于 x86 和 x64 编译器生成类似的零/符号扩展 MOVSX 和 MOVZX。扩展本身并不是免费的,但允许处理器执行无序魔法加速。
但在 RISC-V 上:
因此,无符号和有符号 32 位整数之间的转换是无操作,从有符号 32 位整数到有符号 64 位整数的转换也是如此。
加法和移位需要一些新指令(ADD[I]W/SUBW/SxxW),以确保 32 位值的合理性能。
(C) RISC-V 规范
但与此同时,新型现代 RISC-V 64 位处理器包含 32 位有符号整数指令。为什么?为了提高性能?那么8位和16位在哪里呢?我已经什么都不懂了。
完整的引用对我来说似乎很清楚:
编译器和调用约定维护一个不变式,即所有 32 位值都保存在
64 位寄存器中的符号扩展格式。即使是 32 位无符号整数也会将第 31 位扩展为第 63 位
到 32。
因此,无符号和有符号 32 位整数之间的转换是无操作的,
从有符号 32 位整数到有符号 64 位整数的转换也是如此。
现有64位宽
SLTU 和无符号分支比较仍然可以在无符号 32 位整数上正确运行
这个不变量。
类似地,现有的 32 位符号扩展整数上的 64 位宽逻辑运算
保留符号扩展属性。
一些新指令(ADD[I]W/SUBW/SxxW)是
加法和移位所需的,以确保 32 位值的合理性能。
它表示 32 位值存储在 64 位寄存器中,其 MSb(最高有效位)通过位 32-63 重复。
这是为了both签署并unsigned整数。
这允许进行一些优化,如引用中所述:
- 无符号有符号转换是免费的。
将此与通常的算法进行比较,在通常的算法中,您必须将低 32 位值置零或进行符号扩展,以将其提升为具有不同“符号性”的 64 位值(忽略溢出)。
- 有符号 32 位 有符号 64 位是免费的。
这节省了符号扩展。
- 分支和设置指令仍然有效。
这是因为重复 MSb 不会改变比较结果。
- 逻辑 64 位运算保留此属性
经过几个例子就很容易看出这一点。
然而,加法(举个例子)并不能保留这个不变式: 0x000000007fffffff + 0x0000000000000001 = 0x0000000080000000 这违反了假设。
由于 a) 使用 32 位值的情况经常发生,并且 b) 修复结果需要额外的工作(我可以考虑使用slli
/srai
对)引入了新的指令格式。
这些指令在 64 位寄存器上运行,但仅使用其较低的 32 位值,并对 32 位结果进行符号扩展。
这很容易在硬件中完成,因此值得拥有这种新的指令。
正如评论中所指出的,8 位和 16 位算术很少见,因此没有花费任何工程精力来为其寻找新的空间(无论是在所需的门还是所使用的操作码空间方面)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)