assembly 基于ARM的浮点模数汇编

3npbholx  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(128)

在x86上,有一个浮点取模指令称为fprem,它将堆栈元素0除以堆栈元素1,并将余数留在堆栈元素0中。
现在我正在ARM平台上开发fmodl函数。不知道ARM平台有没有替代指令?

0dxa2lsx

0dxa2lsx1#

我很久没碰ARM了,但据我所知,没有fprem。你可以使用vcvt
阅读了这个 neon docs,我看到利用NEON指令是可能的。在this部分,您可以找到有关FP寄存器的文档。
This文档将帮助您使用vcvt
下面是如何使用vcvt实现的。

vdiv s2, s0, s1  @@ Compute s0/s1
vcvt.s32.f32 s2, s2 @@ Floor the fraction
vcvt.f32.s32 s2, s2 @@ Convert back to float
vmul  s2, s2, s1  @@ Multiply by divisor
vsub  s0, s0, s2  @@ Compute the remainder

字符串
感谢Peter Cordes指出原始答案不足以处理较大的输入。因此,我试图实现一个全面的答案为ARM与双精度输入。在这个答案中,我们还涵盖了一些边缘情况,如符号和NAN。
我试图得到两个设计,其中第一双精度浮点数和第二;单精度浮点数。
以下代码将涵盖双精度输入(Double)。对于32位系统,您可以将d寄存器与s交换。实现或多或少会是这样的。我用更大的输入进行了测试,得到了足够的结果。
对于nan_constant,可以使用0x7fc00000

.global fmod
fmod:
    vcmp.f64 d1, #0
    vmrs APSR_nzcv,FPSCR
    beq NaN
    vabs.f64 d2, d1
    vabs.f64 d3, d0

find_largest_n:
    vcmp.f64 d3, d2
    vmrs APSR_nzcv,FPSCR
    blt finish
    vsub.f64 d3, d3, d2
    b find_largest_n

finish:
    vcmp.f64 d0, #0   @check the sign of the original dividend
    vmrs APSR_nzcv,FPSCR
    bge check_divisor
    vneg.f64 d3, d3  @ Negate d3 if the dividend is negativ

check_divisor:
    vcmp.f64 d1, #0   @check the sign o f the original divisor
    vmrs APSR_nzcv,FPSCR
    bge persist
    vneg.f64 d3, d3  @ negate again if the original divisor ws negative

persist:
    vmov r0, r1, d3
    bx lr

NaN: @for non-numbers
    @ Assuming the NaN constant is at label nan_constant
    ldr r0, =nan_constant
    ldrd r0, r1, [r0]
    bx lr

.section .data
nan_constant:
    .quad 0x7ff8000000000000 @constant NaN for double precision

相关问题