Перевести встроенный ассемблер GCC (SSE2, SSSE3) в встроенные MSVC - PullRequest
1 голос
/ 11 января 2012

Я одалживаю некоторый код из VLC для моего видеопроигрывателя, написанный на MSVC ++ 2010, и не могу найти эквивалент его встроенным ассамам, связанным с извлечением декодированного видеокадра из памяти графического процессора в обычную память.В частности, я не знаю, как перевести эту инструкцию:

movq   %%xmm1,   8(%[dst1])

, которую можно увидеть в функции SplitUV в файле vlc/modules/codec/avcodec/copy.c.

Согласно MSDN, встроенные функциидля movq есть _mm_move_epi64, _mm_loadl_epi64 и _mm_storel_epi64.Тем не менее, они требуют __m128i аргументов, и если я добавлю 1 к указателю к __m128i, я получу смещение 16 байтов, а мне нужно 8 байтов.

Весь код ассемблераследующее:

for (x = 0; x < (width & ~31); x += 32) {
  asm volatile (
    "movdqu (%[shuffle]), %%xmm7\n"
    "movdqa  0(%[src]), %%xmm0\n"
    "movdqa 16(%[src]), %%xmm1\n"
    "movdqa 32(%[src]), %%xmm2\n"
    "movdqa 48(%[src]), %%xmm3\n"
    "pshufb  %%xmm7, %%xmm0\n"
    "pshufb  %%xmm7, %%xmm1\n"
    "pshufb  %%xmm7, %%xmm2\n"
    "pshufb  %%xmm7, %%xmm3\n"
    "movq   %%xmm0,   0(%[dst1])\n"
    "movq   %%xmm1,   8(%[dst1])\n"
    "movhpd %%xmm0,   0(%[dst2])\n"
    "movhpd %%xmm1,   8(%[dst2])\n"
    "movq   %%xmm2,  16(%[dst1])\n"
    "movq   %%xmm3,  24(%[dst1])\n"
    "movhpd %%xmm2,  16(%[dst2])\n"
    "movhpd %%xmm3,  24(%[dst2])\n"
    : : [dst1]"r"(&dstu[x]), [dst2]"r"(&dstv[x]), [src]"r"(&src[2*x]), 
        [shuffle]"r"(shuffle) 
    : "memory"
 );
 ...
}

Я начал переводить построчно, и теперь у меня есть следующий код (неполный):

__m128i x0, x1, x2, x3, x7;
__m128i *pshuffle128 = (__m128i *)shuffle;
__m128i *pSrc = (__m128i *)src;

for (x = 0; x < (width & ~31); x += 32) {
    __m128i *dst1 = (__m128i *)dstu + x;
    __m128i *dst2 = (__m128i *)dstv + x; 
    x7 = _mm_loadu_si128(pshuffle128);  //    "movdqu (%[shuffle]), %%xmm7\n"
    x0 = _mm_load_si128(pSrc + 0);      //    "movdqa  0(%[src]),   %%xmm0\n"
    x1 = _mm_load_si128(pSrc + 1);      //    "movdqa 16(%[src]),   %%xmm1\n"
    x2 = _mm_load_si128(pSrc + 2);      //    "movdqa 32(%[src]),   %%xmm2\n"
    x3 = _mm_load_si128(pSrc + 3);      //    "movdqa 48(%[src]),   %%xmm3\n"
    x0 = _mm_shuffle_epi8(x0, x7);      //    "pshufb  %%xmm7, %%xmm0\n"
    x1 = _mm_shuffle_epi8(x1, x7);      //    "pshufb  %%xmm7, %%xmm1\n"
    x2 = _mm_shuffle_epi8(x2, x7);      //    "pshufb  %%xmm7, %%xmm2\n"
    x3 = _mm_shuffle_epi8(x3, x7);      //    "pshufb  %%xmm7, %%xmm3\n"
    _mm_storel_epi64(dst1 + 0, x0);     //    "movq   %%xmm0,   0(%[dst1])\n"

Следующей инструкцией будет

movq   %%xmm1,   8(%[dst1])

и я не знаю, как указать смещение 8 байтов.Кроме того, у меня есть некоторые сомнения, что я правильно перевел PSHUFB.

Буду очень признателен за комментарии и предложения.

Спасибо.

1 Ответ

2 голосов
/ 11 января 2012

Просто используйте указатель char* для dst, который можно увеличить на 8 и привести к __m128i* при вызове к _mm_storel_epi64, аналогично тому, как это делается здесь (поиск "_mm_storel_epi64 "на этой странице).

...