(おそらく) 同じコードの次の C および ASM バージョンがあります。それが行うことは、それぞれ 2 つの 64 ビット整数で表される 2 つの 128 ビット整数をレジスタ (最初に 4*下位 32 ビット、次に 4*上位 32 ビット) およびADD
/ADC
にロードすることです。ADD
これは十分に単純なコードであり、ARM/ST のマニュアルでは実際に 96 ビット (3 / ADC
s)で同じ例を示しています。
単純な呼び出しの場合、両方のバージョンが機能します (繰り返し追加(1 << x++)
または 1..x)。しかし、より長いテストスイートでは、ARM アセンブリが失敗します (ボードがハングします)。ATM 私はそれをトラップ/デバッグする能力がなくprintf()
、テストの失敗を見つけるために何も使用できません。これはとにかく無関係です.C バージョンは期待どおりに動作するため、ASM バージョンにはいくつかの基本的な障害があるはずです。
わかりません。これは十分に単純で、C アセンブリの出力に非常に近いものです (sans branching)。「メモリ」制約を試しました(必要ないはずです)。下位64ビットと上位64ビットの間のキャリーをレジスタに保存し、後で追加してADD(C).W
、 、アライメント、LDR
/STR
の代わりに2つのLDRD
/STRD
などを使用してみました。一部の加算がうまくいかず、0 による除算などの結果になるため、ボード フォールトが発生します。GCC ASM は以下にあり、同様の基本的な手法を使用しているため、問題は見られません。
私は本当にそのコードを具体的に修正するのではなく、追加を行うための最速の方法を探しています。rX
とを指定するための制約がないため、定数レジスタ名を使用する必要があるのは残念ですrX+1
。また、コンパイル中に不足するため、GCC と同じ数のレジスタを使用することは不可能です。
typedef struct I128 {
int64_t high;
uint64_t low;
} I128;
I128 I128add(I128 a, const I128 b) {
#if defined(USEASM) && defined(ARMx)
__asm(
"LDRD %%r2, %%r3, %[alo]\n"
"LDRD %%r4, %%r5, %[blo]\n"
"ADDS %%r2, %%r2, %%r4\n"
"ADCS %%r3, %%r3, %%r5\n"
"STRD %%r2, %%r3, %[alo]\n"
"LDRD %%r2, %%r3, %[ahi]\n"
"LDRD %%r4, %%r5, %[bhi]\n"
"ADCS %%r2, %%r2, %%r4\n"
"ADC %%r3, %%r3, %%r5\n"
"STRD %%r2, %%r3, %[ahi]\n"
: [alo] "+m" (a.low), [ahi] "+m" (a.high)
: [blo] "m" (b.low), [bhi] "m" (b.high)
: "r2", "r3", "r4", "r5", "cc"
);
return a;
#else
// faster to use temp than saving low and adding to a directly
I128 r = {a.high + b.high, a.low + b.low};
// check for overflow of low 64 bits, add carry to high
// avoid conditionals
//r.high += r.low < a.low || r.low < b.low;
// actually gcc produces faster code with conditionals
if(r.low < a.low || r.low < b.low) ++r.high;
return r;
}
「armv7m-none-eabi-gcc-4.7.2 -O3 -ggdb -fomit-frame-pointer -falign-functions=16 -std=gnu99 -march=armv7e-m」を使用する GCC C バージョン:
b082 sub sp, #8
e92d 0ff0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp}
a908 add r1, sp, #32
e881 000c stmia.w r1, {r2, r3}
e9dd 890e ldrd r8, r9, [sp, #56] ; 0x38
e9dd 670a ldrd r6, r7, [sp, #40] ; 0x28
e9dd 2308 ldrd r2, r3, [sp, #32]
e9dd 450c ldrd r4, r5, [sp, #48] ; 0x30
eb16 0a08 adds.w sl, r6, r8
eb47 0b09 adc.w fp, r7, r9
1912 adds r2, r2, r4
eb43 0305 adc.w r3, r3, r5
45bb cmp fp, r7
bf08 it eq
45b2 cmpeq sl, r6
d303 bcc.n 8012c9a <I128add+0x3a>
45cb cmp fp, r9
bf08 it eq
45c2 cmpeq sl, r8
d204 bcs.n 8012ca4 <I128add+0x44>
2401 movs r4, #1
2500 movs r5, #0
1912 adds r2, r2, r4
eb43 0305 adc.w r3, r3, r5
e9c0 2300 strd r2, r3, [r0]
e9c0 ab02 strd sl, fp, [r0, #8]
e8bd 0ff0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp}
b002 add sp, #8
4770 bx lr
失敗する ASM バージョン:
b082 sub sp, #8
b430 push {r4, r5}
a902 add r1, sp, #8
e881 000c stmia.w r1, {r2, r3}
e9dd 2304 ldrd r2, r3, [sp, #16]
e9dd 4508 ldrd r4, r5, [sp, #32]
1912 adds r2, r2, r4
416b adcs r3, r5
e9cd 2304 strd r2, r3, [sp, #16]
e9dd 2302 ldrd r2, r3, [sp, #8]
e9dd 4506 ldrd r4, r5, [sp, #24]
4162 adcs r2, r4
eb43 0305 adc.w r3, r3, r5
e9cd 2302 strd r2, r3, [sp, #8]
4604 mov r4, r0
c90f ldmia r1, {r0, r1, r2, r3}
e884 000f stmia.w r4, {r0, r1, r2, r3}
4620 mov r0, r4
bc30 pop {r4, r5}
b002 add sp, #8
4770 bx lr