2012-02-28 7 views
1

私はCコードをリバースエンジニアリングしようとしていますが、この部分のアセンブリは本当に理解できません。私はそれがSSE拡張の一部であることを知っています。しかし、何かは実際に私がx86命令で慣れていたものとはまったく異なります。CコードのSSE2命令

static int sad16_sse2(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h) 
{ 
    int ret; 
    __asm__ volatile(
     "pxor %%xmm6, %%xmm6   \n\t" 
     ASMALIGN(4) 
     "1:        \n\t" 
     "movdqu (%1), %%xmm0   \n\t" 
     "movdqu (%1, %3), %%xmm1  \n\t" 
     "psadbw (%2), %%xmm0   \n\t" 
     "psadbw (%2, %3), %%xmm1  \n\t" 
     "paddw %%xmm0, %%xmm6   \n\t" 
     "paddw %%xmm1, %%xmm6   \n\t" 
     "lea (%1,%3,2), %1    \n\t" 
     "lea (%2,%3,2), %2    \n\t" 
     "sub $2, %0      \n\t" 
     " jg 1b       \n\t" 
     : "+r" (h), "+r" (blk1), "+r" (blk2) 
     : "r" ((x86_reg)stride) 
    ); 
    __asm__ volatile(
     "movhlps %%xmm6, %%xmm0   \n\t" 
     "paddw %%xmm0, %%xmm6   \n\t" 
     "movd %%xmm6, %0    \n\t" 
     : "=r"(ret) 
    ); 
    return ret; 
} 

%1、%2、%3とは何ですか? (%1、%2、%3)はどういう意味ですか?また、 "+ r"、 " - r"、 "= r"はどういう意味ですか?

+0

このコードの_two disjointed_ inlineアセンブリブロックの使用は無効です。それはうまくいくかもしれませんが、無限の知恵のコンパイラが2番目の '__asm__'ブロックの"宣言されていない入力 "(regs'%xmm0'/'%xmm6')を使って何かを行うことを選択するかもしれないからです。それを修正する方法の詳細については、http://stackoverflow.com/questions/8891139/why-is-this-inline-assembly-not-workingを参照してください。 –

答えて

0

インラインアセンブラは、マクロプリプロセッサと同様に動作します。彼らはパラメータリストに表示される正確に一つの有力パーセントとオペランドは、この場合には、順番に入力パラメータで置き換えられます:

%0 h    output, register, r/w 
%1 blk1    output, register, r/w 
%2 blk2    output, register, r/w 
%3 (x86_reg)stride input, register, read only 

パラメータは、通常のCの式です。これらは "constraints"でさらに指定することができます。この場合、 "r"はメモリオペランドである "m"とは反対のレジスタに値があることを意味します。制約修飾子 "= r"はこれを書込み専用オペランドにし、 "+ r"を読取り/書込みオペランドとし、 "r"と通常読取りオペランドとする。

最初のコロンの後に、出力オペランドが表示されます.2番目の入力オペランドの後に、およびオプションの3番目のclobberedレジスタの後に出力オペランドが表示されます。

したがって命令シーケンスは、各バイトの絶対差の合計をblk1blk2と計算します。これは16バイトのブロックで発生するため、strideが16の場合はブロックが連続します。そうでない場合は穴があります。いくつかの最小ループ展開が行われるため、各命令は2回表示され、hパラメータは処理する32バイトブロックの数です。 psadbw命令は、デスティネーションレジスタの下位16ビットでのみ集計されるため、2番目のasmブロックは役に立たないようです。 (いくつかのコードを省略しましたか?)