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

Mar*_*oli 1 floating-point assembly neon arm64 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'"
Run Code Online (Sandbox Code Playgroud)

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

另一个问题是:根据arm 的网站,它支持使用浮点寄存器作为 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'”

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

fuz*_*fuz 7

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

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

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

ldr d1, =0x4040000000000000
Run Code Online (Sandbox Code Playgroud)

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

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

mov x0, #0x4040000000000000
fmov d1, x0
Run Code Online (Sandbox Code Playgroud)

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

movi d1, #0
Run Code Online (Sandbox Code Playgroud)

这将清除d1寄存器(并且因此b1h1s1,和q1寄存器,太)。