[英]How do I move a floating point constant into an FP register?
因此,我正在使用 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 的網站,它支持使用浮點寄存器作為 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×2 r ,其中n是 16 ≤ n ≤ 31 范圍內的整數, r是 -3 ≤ n ≤ 4 范圍內的整數。
ARMv8 體系結構參考手冊中給出了支持數字的確切列表。 此外, fmov
僅適用於 16、32 和 64 位數據大小,因為沒有為 ARMv8 指定 8 位或 128 位浮點格式。 對於不支持FEAT_FP16
ARMv8 內核,也不支持 16 位數據大小。 ARMv8 在很多這樣的地方缺乏正交性; 並非所有指令都適用於所有操作數大小。
對於一個簡單的替代解決方案,使用ldr
代替文字池中的常量(您需要手動將其轉換為整數)。 例如,要加載32.0
, 0x4040000000000000
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
寄存器(因此也清除b1
、 h1
、 s1
和q1
寄存器)。
我來晚了,但我(一個業余愛好者)想出了如何使用 .data 將浮點數加載到寄存器中。 這是我打印 PI 的示例代碼。 我希望它能幫助其他人,因為我花了大約兩個小時試圖自己解決這個問題。 -- Jds
.global main
.align 4
main:
ADRP X1, pi@PAGE // Load the address for our "pi" data
ADD X1, X1, pi@PAGEOFF
LDR D1, [X1] // Store the contents of X1 to D1
STR D1, [SP, #-16]! // Store the float (D1) onto the stack for printing
ADRP X0, format@PAGE // Load the address of our printf format string
ADD X0, X0, format@PAGEOFF
end:
BL _printf // print -- reads string from X0 and data from stack
mov X16, #1
svc 0
.data
pi: .double 3.141519
format: .asciz "Pi is %f \n"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.