1

私はこれまで実際に使用したことのないベクトル演算を使用するためにアセンブリを試みていますが、構文の一部を把握するのに少し苦労していることは確かです。

関連するコードは以下です。

unit16_t asdf[4];
asdf[0] = 1;
asdf[1] = 2;
asdf[2] = 3;
asdf[3] = 4;
uint16_t other = 3;

__asm__("movq %0, %%mm0"
        :
        : "m" (asdf));
__asm__("pcmpeqw %0, %%mm0"
        :
        : "r" (other));
__asm__("movq %%mm0, %0" : "=m" (asdf));

printf("%u %u %u %u\n", asdf[0], asdf[1], asdf[2], asdf[3]);

この単純な例では、配列内の各要素に対して "3" の 16 ビット比較を実行しようとしています。出力が「0 0 65535 0」になることを願っています。でも、まとまりません。

最初のアセンブリ命令で次のエラーが表示されます。

エラー: メモリ入力 0 は直接アドレス指定できません

2 番目の命令では、別のエラーが表示されます。

エラー: `pcmpeqw' のサフィックスまたはオペランドが無効です

どんな助けでも大歓迎です。

4

4 に答える 4

4

レジスターを gcc asm ステートメントで直接使用することはできず、レジスターが他の asm ステートメントの何かと一致することを期待できません。オプティマイザーが物事を動かします。代わりに、適切な型の変数を宣言し、制約を使用して、それらの変数を使用している命令の正しい種類のレジスタに強制する必要があります。

MMX/SSE に関連する制約は、xmm レジスターxとmmx レジスターです。yあなたの例では、次のことができます。

#include <stdint.h>
#include <stdio.h>

typedef union xmmreg {
    uint8_t   b[16];
    uint16_t  w[8];
    uint32_t  d[4];
    uint64_t  q[2];
} xmmreg;

int main() {
    xmmreg v1, v2;
    v1.w[0] = 1;
    v1.w[1] = 2;
    v1.w[2] = 3;
    v1.w[3] = 4;
    v2.w[0] = v2.w[1] = v2.w[2] = v2.w[3] = 3;
    asm("pcmpeqw %1,%0" : "+x"(v1) : "x"(v2));
    printf("%u %u %u %u\n", v1.w[0], v1.w[1], v1.w[2], v1.w[3]);
}

32 番目のベクトルのすべての関連要素にわたって明示的に複製する必要があることに注意してください。

于 2014-02-24T21:41:26.473 に答える
3

インテルのリファレンス マニュアルから:

PCMPEQW mm, mm/m64        Compare packed words in mm/m64 and mm for equality.
PCMPEQW xmm1, xmm2/m128   Compare packed words in xmm2/m128 and xmm1 for equality.

間違っpcmpeqwた「r」レジスタを使用しています。「mm」と「m64」レジスタのみ

ヴァルター

于 2014-02-24T19:03:40.073 に答える