【问题标题】:Translate GCC inline asm (SSE2, SSSE3) to MSVC intrinsics将 GCC 内联汇编(SSE2、SSSE3)转换为 MSVC 内部函数
【发布时间】:2012-02-07 22:46:22
【问题描述】:

我从 VLC 中借用一些代码到我的视频播放器中,用 MSVC++ 2010 编写,但找不到与其内联汇编等效的代码,这些代码与将解码的视频帧从 GPU 内存提取到常规内存有关。 特别是,我不知道如何翻译这条指令:

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

可以在文件vlc/modules/codec/avcodec/copy.c中的函数SplitUV中看到。

根据 MSDN,movq 的内在函数是 _mm_move_epi64_mm_loadl_epi64_mm_storel_epi64。 但是,它们需要 __m128i 参数,如果我在指向 __m128i 的指针上加 1,我将获得 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。

非常感谢 cmets 和建议。

谢谢。

【问题讨论】:

  • 我不是这方面的专家,但我相信有两个编译器共享的内在函数,你应该瞄准使用这些。
  • 不,没有这样的事情。 x86 的 MSVC 也可以使用内联 asm,但 x64 的 MSVC - 不能。
  • 同时,有 2 个错误。 (1)我已经切换了dstu和dstv (2)pSrc必须在循环体中赋值为(__m128i *)(src+2*x)

标签: visual-c++ gcc inline-assembly sse2


【解决方案1】:

只需为dst 使用char* 指针,您可以将其递增8,然后在对_mm_storel_epi64 的调用中将其转换为__m128i*,类似于here 的完成方式(在其上搜索“_mm_storel_epi64”页)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-07
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多