我正在学习 MicroPython 的汇编程序(PyBoard 的 ARM Thumb2 指令集)。
有没有比这更快的方法来检查 FPU 寄存器(s0)的符号(正/负)?
@micropython.asm_thumb
def float_array_abs(r0, r1):
label(LOOP)
vldr(s0, [r0, 0])
vmov(r2, s0) # 1
cmp(r2, 0) # 2
itt(mi) # 3
vneg(s0, s0)
vstr(s0, [r0, 0])
add(r0, 4)
sub(r1, 1)
bgt(LOOP)
这可行,但它似乎不是“正确”的解决方案(不确定 的符号r2
总是与 的符号匹配s0
),我怀疑它必须在少于两个指令中是可能的。
更新 1:
根据评论(谢谢),我进一步提高了代码的速度:
@micropython.asm_thumb
def float_array_abs1(r0, r1):
label(LOOP)
ldr(r2, [r0, 0])
cmp(r2, 0) # this works for some reason
bge(SKIP)
vmov(s0, r2)
vneg(s0, s0)
vstr(s0, [r0, 0]) # this can be skipped if not negative
label(SKIP)
add(r0, 4)
sub(r1, 1)
bgt(LOOP)
但它仍然留下一个问题,这是确定 FP 值符号的可靠方法吗?
以下是我系统上四个浮点值的字节表示形式供参考:
-1.0 0xbf800000
-0.0 0x80000000
0.0 0x00000000
1.0 0x3f800000
我想如果这取决于硬件,那么我不应该依赖它来确定标志......
我认为这可能是“正确”的做法(即正确的 FPU 比较):
def float_array_abs2(r0, r1):
mov(r2, 0)
vmov(s1, r2)
label(LOOP)
vldr(s0, [r0, 0])
vcmp(s0, s1)
vmrs(APSR_nzcv, FPSCR)
itt(mi)
vneg(s0, s0)
vstr(s0, [r0, 0])
add(r0, 4)
sub(r1, 1)
bgt(LOOP)
但我对此进行了计时,它比上面的代码慢了 11% ( float_array_abs1
)。因此,如果它是一个可靠的解决方案,那么使用早期的代码会很好。
更新 2:
@Ped7g 提出了该方法and 0x7FFFFFFF
(见评论)。
我对此进行了测试,它确实有效。这是代码:
@micropython.asm_thumb
def float_array_abs3(r0, r1):
movwt(r3, 0x7FFFFFFF)
label(LOOP)
ldr(r2, [r0, 0])
and_(r2, r3)
str(r2, [r0, 0])
add(r0, 4)
sub(r1, 1)
bgt(LOOP)
更正:它比float_array_abs1
上面更快。这似乎是最好的解决方案,但它是否强大?