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
来自其他地方的一些复制意大利面为整数除法:基本上每位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)
编译器通常在其库中包含一个分隔符,例如 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 来说,它应该自动工作,你不需要像我那样做。其他编译器也不需要像我在上面的冒险游戏中那样做。