2012-01-11 3 views
1

Я заимствую некоторый код из VLC для своего видеопроигрывателя, написанный на MSVC++ 2010, и не могу найти эквивалент его встроенных asms, связанных с извлечением декодированного видеокадра из память GPU в обычную память. В частности, я не знаю, как перевести эту инструкцию:Перевести GCC inline asm (SSE2, SSSE3) на MSVC intrinsics

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.

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

Спасибо.

+0

Я не эксперт по этому вопросу, но я верю, что есть внутренности, которые разделяют оба компилятора, вы должны стремиться использовать их. –

+0

Нет, нет такой вещи. MSVC для x86 также может использовать встроенный asm, но MSVC для x64 - не может. – wl2776

+0

Между тем, есть 2 ошибки. (1) Я переключил dstu и dstv (2) pSrc должен быть назначен в теле цикла на значение (__m128i *) (src + 2 * x) – wl2776

ответ

2

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

+0

Спасибо, это сработало! – wl2776

Смежные вопросы