GASインラインアセンブリでアセンブリロング追加を書いているのですが、
template <std::size_t NumBits>
void inline KA_add(vli<NumBits> & x, vli<NumBits> const& y);
私が専門とするなら、私はできる:
template <>
void inline KA_add<128>(vli<128> & x, vli<128> const& y){
asm("addq %2, %0; adcq %3, %1;" :"+r"(x[0]),"+r"(x[1]):"g"(y[0]),"g"(y[1]):"cc");
}
テンプレートのインラインを許可するように一般化して、任意の長さでコンパイラを動作させようとすると、うまくいきます...
template <std::size_t NumBits>
void inline KA_add(vli<NumBits> & x, vli<NumBits> const& y){
asm("addq %1, %0;" :"+r"(x[0]):"g"(y[0]):"cc");
for(int i(1); i < vli<NumBits>::numwords;++i)
asm("adcq %1, %0;" :"+r"(x[i]):"g"(y[i]):"cc");
};
キャリー ビット (CB) が伝搬されるという保証はありません。最初の asm 行と 2 番目の行の間では保存されません。ループが i をインクリメントして CB I を「削除」するため、2 つの ASM 呼び出しで CB を保存するための GAS 制約が存在する必要があるため、論理的である可能性があります。残念ながらそのような情報は見つかりません。
何か案が ?
ありがとう、メルシー!
PS関数を書き直して、C++のイデオロギーを取り除きます
template <std::size_t NumBits>
inline void KA_add_test(boost::uint64_t* x, boost::uint64_t const* y){
asm ("addq %1, %0;" :"+r"(x[0]):"g"(y[0]):"cc");
for(int i(1); i < vli<NumBits>::numwords;++i)
asm ("adcq %1, %0;" :"+r"(x[i]):"g"(y[i]):"cc");
};
asmは(GCCデバッグモード)、
アプリ
addq %rdx, %rax;
NO_APP
movq -24(%rbp), %rdx
movq %rax, (%rdx)
.LBB94: .loc 9 55 0
movl $1, -4(%rbp)
jmp .L323
.L324:
.loc 9 56 0
movl -4(%rbp), %eax
cltq
salq $3, %rax
movq %rax, %rdx
addq -24(%rbp), %rdx <----------------- Break the carry bit
movl -4(%rbp), %eax
cltq
salq $3, %rax
addq -32(%rbp), %rax
movq (%rax), %rcx
movq (%rdx), %rax
アプリ
adcq %rcx, %rax;
NO_APP
追加のaddqがあることが読み取れるように、CBの伝播を破壊します