assembly - 如何将浮点常量移动到 FP 寄存器中?

标签 assembly floating-point arm64 neon immediate-operand

因此,我正在使用 A64 指令集以汇编形式的 ARM 进行编程。 我正在使用指令 fmov d1, #31.0 将值移动到 dx 寄存器。 但是,当我使用 0.0 或任何高于 31.0 的值时,它会显示错误:

"Error: invalid floating-point constant at operand 2 -- `fmov d1,#32.0'"

那么,如何在 A64 上定义浮点常量呢?为什么我不能使用任何大于 31 的值或使用 0?如何用十六进制表示值?

另一个问题是:根据arm's website它支持使用浮点寄存器作为 Bx、Hx、Sx、Dx 和 Qx(分别为 8、16、34、64 和 128 位),但我不能使用 Bx、Hx 和 Qx 寄存器,它显示:

“错误:操作数不匹配——‘fmov b1,#1.0’”

“错误:所选处理器不支持 `fmov h1,#2.0”

“错误:操作数不匹配——‘fmov q1,#2.0’”

如何正确设置第二个操作数?

最佳答案

fmov 只能使用一组非常小的浮点常量,因为常量在指令中被编码为 8 位立即数。具体来说,它必须可以表示为 ±n/16×2r,其中 n 是范围内的整数16 ≤ n ≤ 31 且r 是-3 ≤ n ≤ 4 范围内的整数。

ARMv8 Architecture Reference Manual 中给出了受支持数字的确切列表。此外,fmov 仅适用于 16、32 和 64 位数据大小,因为没有ARMv8 指定了 8 位或 128 位浮点格式。对于不支持 FEAT_FP16 的 ARMv8 内核,也不支持 16 位数据大小。 ARMv8 在很多地方都缺乏正交性;并非所有指令都适用于所有操作数大小。

对于一个简单的替代解决方案,使用 ldr 代替文字池中的常量(您需要手动将其转换为整数)。例如,要加载 32.0,请将 32.0 转换为其 IEEE 754 表示,为您提供 0x4040000000000000。然后你可以像这样加载这个常量:

ldr d1, =0x4040000000000000

带有 SIMD&FP 寄存器和文字池中的值的 ldr 指令可用于 32 位、64 位和 128 位操作数大小。较小的操作数大小不适用于文字池寻址模式。如果要加载 8 位或 16 位寄存器,请改为加载相应的 32 位寄存器。

一个稍快的解决方案是首先将所需的数字加载到通用寄存器(支持更灵活地生成立即数),然后将其移动到 SIMD 和 FP 寄存器中:

mov x0, #0x4040000000000000
fmov d1, x0

要加载 0.0 或掩码,请使用 movi 指令。该指令的合法立即数集取决于操作数的大小。但是对于你的情况,这只是

movi d1, #0

这会清除 d1 寄存器(以及 b1h1s1 q1 也注册了)。

关于assembly - 如何将浮点常量移动到 FP 寄存器中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64608307/

相关文章:

c++ - cuda 数学函数 norm3df 是否溢出?

ios - Apple 告诉 iOS8 上扩展的 64 位要求是什么意思?

iOS 7.1 更新到 Xcode 5.1 后出现错误

linux - 共享库中的重定位条目

assembly - 从汇编语言运行另一个程序

algorithm - 如何将此排序算法转换为 mips 程序集

visual-c++ - 如何将汇编标记放入 C++ 代码 (x64)

java - 将 IEEE-754 double 和单精度转换为十进制 Java bug

c - 如何在程序集中获取 atof() 函数(来自 msvcrt.dll)的双返回值?

cmake - 为什么android ndk独立工具链不支持带有api 19的arm64但android ndk cmake支持