assembly - 零/符号扩展是无操作的,为什么每种尺寸类型的说明?
问题描述
对于 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 重复。
这对有符号和无符号整数都是如此。
这允许进行一些优化,如报价中所述:
- 无符号 <-> 有符号转换是免费的。
将此与通常的算法进行比较,您必须将低 32 位值归零或符号扩展以将其提升为不同“符号”的 64 位值(忽略溢出)。 - 带符号的 32 位 <-> 带符号的 64 位是免费的。
这省去了一个符号扩展。 - 分支和设置指令仍然有效。
这是因为重复 MSb 不会改变比较结果。 - 逻辑 64 位操作保留了这个属性
通过几个例子很容易看出这一点。
然而,加法(仅举一个例子)并没有保留这个不变量: 0x000000007fffffff + 0x0000000000000001 = 0x0000000080000000 这违反了假设。
由于 a) 使用 32 位值经常发生并且 b) 修复结果需要额外的工作(我可以考虑使用slli
/srai
对),因此引入了一种新的指令格式。
这些指令对 64 位寄存器进行操作,但只使用它们的低 32 位值,并对 32 位结果进行符号扩展。
这很容易在硬件中完成,因此值得拥有这种新的指令。
正如评论中所指出的,8 位和 16 位算术很少见,因此没有花费任何工程精力为其寻找新空间(无论是在所需的门方面还是在使用的操作码空间方面)。
推荐阅读
- python - Jupyter Dropdown ipywidget 显示错误的数据框
- ruby-on-rails - 添加 Node buildpack 后 Rails 应用程序不会部署
- angular - 在 app 模块中或仅在其他模块中导入模块和路由之间的区别?
- python - 为什么 Python 中的 Selenium 不会点击弹出的隐私按钮?
- python-3.x - 如何使用 python 3 tkinter/guizero 在主窗口中间启动第二个窗口?
- r - R下载压缩的ACS数据文件的问题
- google-sheets - 希望将 HTML 信息导入 Google 工作表
- stored-procedures - 如果存在则删除并创建表,如果不存在则在 oracle 中创建过程
- python - 如何处理大型 json 文件(将其展平为 tsv)
- cryptography - HLK/HCK 文件的数字签名