私は過去に多くの固定小数点演算を行い、自分で高速な 64/32 ビット除算を探して多くの調査を行いました。「ARM部門」をグーグルで検索すると、この問題に関する素晴らしいリンクと議論がたくさん見つかります。
ハードウェアで 32 ビット除算さえ利用できない可能性がある ARM アーキテクチャの最適なソリューションは次のとおりです。
http://www.peter-teichmann.de/adiv2e.html
このアセンブリ コードは非常に古いため、アセンブラはその構文を理解できない可能性があります。ただし、コードをツールチェーンに移植する価値はあります。これは、私がこれまでに見た特別なケースの最速の除算コードであり、私を信頼してください:私はそれらすべてをベンチマークしました:-)
前回実行したとき (約 5 年前、CortexA8 の場合)、このコードはコンパイラが生成したコードよりも約 10 倍高速でした。
このコードは NEON を使用しません。NEONポートは面白いでしょう。ただし、パフォーマンスが大幅に向上するかどうかはわかりません。
編集:
GAS (GNU Toolchain) にアセンブラを移植したコードを見つけました。このコードは動作し、テストされています:
割るS
.section ".text"
.global udiv64
udiv64:
adds r0,r0,r0
adc r1,r1,r1
.rept 31
cmp r1,r2
subcs r1,r1,r2
adcs r0,r0,r0
adc r1,r1,r1
.endr
cmp r1,r2
subcs r1,r1,r2
adcs r0,r0,r0
bx lr
C コード:
extern "C" uint32_t udiv64 (uint32_t a, uint32_t b, uint32_t c);
int32_t fixdiv24 (int32_t a, int32_t b)
/* calculate (a<<24)/b with 64 bit immediate result */
{
int q;
int sign = (a^b) < 0; /* different signs */
uint32_t l,h;
a = a<0 ? -a:a;
b = b<0 ? -b:b;
l = (a << 24);
h = (a >> 8);
q = udiv64 (l,h,b);
if (sign) q = -q;
return q;
}