如何对ARM进行整数(有符号或无符号)除法?

Pho*_*non 17 assembly arm instruction-set integer-division cortex-a8

我正在研究Cortex-A8和Cortex-A9.我知道有些架构没有整数除法,但除了转换为float,divide,转换为整数之外,最好的方法是什么?或者这确实是最好的解决方案?

干杯! =)

Wil*_*eld 10

通过执行64位乘法和右移,可以快速完成除以常数值的除法,例如,如下所示:

LDR     R3, =0xA151C331
UMULL   R3, R2, R1, R3
MOV     R0, R2,LSR#10
Run Code Online (Sandbox Code Playgroud)

这里R1除以1625.计算如下:64bitreg(R2:R3)= R1*0xA151C331,然后结果是右移32位的高32位:

R1*0xA151C331/2^(32+10) = R1*0.00061538461545751488 = R1/1624.99999980
Run Code Online (Sandbox Code Playgroud)

您可以从此公式计算自己的常量:

x / N ==  (x*A)/2^(32+n)   -->       A = 2^(32+n)/N
Run Code Online (Sandbox Code Playgroud)

选择最大的n,其中A <2 ^ 32


Mic*_*gan 7

来自其他地方的一些复制意大利面为整数除法:基本上每位3个指令.从这个网站,虽然我也看到过很多其他地方. 这个网站也有一个很好的版本,一般来说可能更快.


@ Entry  r0: numerator (lo) must be signed positive
@        r2: deniminator (den) must be non-zero and signed negative
idiv:
        lo .req r0; hi .req r1; den .req r2
        mov hi, #0 @ hi = 0
        adds lo, lo, lo
        .rept 32 @ repeat 32 times
          adcs hi, den, hi, lsl #1
          subcc hi, hi, den
          adcs lo, lo, lo
        .endr
        mov pc, lr @ return
@ Exit   r0: quotient (lo)
@        r1: remainder (hi)
Run Code Online (Sandbox Code Playgroud)

  • 这是每位3个指令,但不是每位3个周期.每个步骤中的所有指令都立即依赖于前一个的标志设置,这意味着结果延迟3-4个周期,具体取决于内核.这可能需要每步9-12个循环,总共约360个循环. (5认同)

old*_*mer 4

编译器通常在其库中包含一个分隔符,例如 gcclib 我已从 gcc 中提取它们并直接使用它们:

https://github.com/dwelch67/stm32vld/然后是 stm32f4d/adventure/gcclib

漂浮并返回可能不是最好的解决方案。你可以尝试一下,看看它有多快......这是一个乘法,但也可以很容易地使它成为一个除法:

https://github.com/dwelch67/stm32vld/然后是 stm32f4d/float01/vectors.s

不过我没有计时来看看有多快/慢。明白了,我在上面使用的是 cortex-m,而你正在谈论 cortex-a,频谱的不同端,类似的浮点指令,gcc lib 的东西是相似的,对于 cortex-m,我必须为拇指构建,但你可以同样轻松地为 Arm 构建。实际上,对于 gcc 来说,它应该自动工作,你不需要像我那样做。其他编译器也不需要像我在上面的冒险游戏中那样做。