zoukankan      html  css  js  c++  java
  • [C] zintrin.h: 智能引入intrinsic函数 V1.02版。支持VC2012,增加INTRIN_ALIGN、INTRIN_COMPILER_NAME宏

    作者:zyl910

    一、更新说明

    1.1 支持VC2012

      VC2012增加了很多Intrinsics函数,详见——
    http://www.cnblogs.com/zyl910/archive/2012/11/06/intrin_vc2012.html
    检查了一下VC2012新增的Intrinsics函数集,发现它支持ARM指令和Haswell新指令

      根据上述信息改进zintrin,检测到是VC2012时定义相关的宏——

            #if _MSC_VER >=1700    // VC2012
                #define INTRIN_AVX2    1    // immintrin.h
                #define INTRIN_FMA    1    // immintrin.h
                #define INTRIN_F16C    1    // immintrin.h
                #define INTRIN_RDRND    1    // immintrin.h
                #define INTRIN_FSGSBASE    1    // immintrin.h
                #define INTRIN_TBM    1    // ammintrin.h
                #define INTRIN_LZCNT    1    // immintrin.h
                #define INTRIN_BMI    1    // immintrin.h
                #define INTRIN_BMI2    1    // immintrin.h
                #define INTRIN_INVPCID    1    // immintrin.h
                #define INTRIN_HLE    1    // immintrin.h
                #define INTRIN_RTM    1    // immintrin.h
            #endif

      INVPCID、HLE、RTM是Haswell的新指令,原先的“INTRIN_*”判断宏没有它们。于是增加了这几个定义——
    INTRIN_INVPCID
    INTRIN_HLE
    INTRIN_RTM


      通过对比VC2010与VC2012的头文件后发现——虽然以前intrin.h支持lzcnt,但它是双下划线版的,而不是Intel所规定的单下划线版。直到VC2012,才支持单下划线版lzcnt。
      具体修正做法——注释掉以前的INTRIN_LZCNT。检测到是VC2012时,才定义INTRIN_LZCNT。


    1.2 增加INTRIN_ALIGN宏(地址对齐)

      在使用SIMD指令时,经常需要地址对齐。例如 MMX要求8字节对齐,SSE要求16字节对齐,AVX要求32字节对齐。
      因C语言标准未考虑该问题,VC与GCC的实现方法都不同。于是我定义一个INTRIN_ALIGN宏,用来统一处理地址对齐问题——

    #if defined(__GNUC__)    // GCC
        #define INTRIN_ALIGN(n)    __attribute__((aligned(n)))
    #else    // 否则使用VC格式.
        #define INTRIN_ALIGN(n)    __declspec(align(n))
    #endif    // #if defined(__GNUC__)    // GCC

      使用时,将该宏写在数据类型的前面。例如——
    INTRIN_ALIGN(32) uint_16 buf[16];


    1.3 增加INTRIN_COMPILER_NAME宏(编译器名称)

      在使用Intrinsics函数时,经常需要得知编译器名称,以方便进行对比分析。于是我定义了INTRIN_COMPILER_NAME宏——

    #define INTRIN_MACTOSTR(x)    #x
    #define INTRIN_MACROVALUESTR(x)    INTRIN_MACTOSTR(x)
    #if defined(__ICL)    // Intel C++
    #  if defined(__VERSION__)
    #    define INTRIN_COMPILER_NAME    "Intel C++ " __VERSION__
    #  elif defined(__INTEL_COMPILER_BUILD_DATE)
    #    define INTRIN_COMPILER_NAME    "Intel C++ (" INTRIN_MACROVALUESTR(__INTEL_COMPILER_BUILD_DATE) ")"
    #  else
    #    define INTRIN_COMPILER_NAME    "Intel C++"
    #  endif    // #  if defined(__VERSION__)
    #elif defined(_MSC_VER)    // Microsoft VC++
    #  if defined(_MSC_FULL_VER)
    #    define INTRIN_COMPILER_NAME    "Microsoft VC++ (" INTRIN_MACROVALUESTR(_MSC_FULL_VER) ")"
    #  elif defined(_MSC_VER)
    #    define INTRIN_COMPILER_NAME    "Microsoft VC++ (" INTRIN_MACROVALUESTR(_MSC_VER) ")"
    #  else
    #    define INTRIN_COMPILER_NAME    "Microsoft VC++"
    #  endif    // #  if defined(_MSC_FULL_VER)
    #elif defined(__GNUC__)    // GCC
    #  if defined(__CYGWIN__)
    #    define INTRIN_COMPILER_NAME    "GCC(Cygmin) " __VERSION__
    #  elif defined(__MINGW32__)
    #    define INTRIN_COMPILER_NAME    "GCC(MinGW) " __VERSION__
    #  else
    #    define INTRIN_COMPILER_NAME    "GCC " __VERSION__
    #  endif    // #  if defined(_MSC_FULL_VER)
    #else
    #  define INTRIN_COMPILER_NAME    "Unknown Compiler"
    #endif    // #if defined(__ICL)    // Intel C++

      示例——
    printf("Compiler: %s\n", INTRIN_COMPILER_NAME);

    二、全部代码

    2.1 zintrin.h

      全部代码——

    View Code
    #ifndef __ZINTRIN_H_INCLUDED
    #define __ZINTRIN_H_INCLUDED
    
    #include "stdint.h"
    #if !defined(PTRDIFF_MAX) || !defined(INT32_MAX)
    #error Need C99 marcos: __STDC_LIMIT_MACROS.
    #endif
    
    
    // INTRIN_ALIGN(x): 变量地址对齐.
    #if defined(__GNUC__)    // GCC
        #define INTRIN_ALIGN(n)    __attribute__((aligned(n)))
    #else    // 否则使用VC格式.
        #define INTRIN_ALIGN(n)    __declspec(align(n))
    #endif    // #if defined(__GNUC__)    // GCC
    
    // INTRIN_COMPILER_NAME: 编译器名称.
    #define INTRIN_MACTOSTR(x)    #x
    #define INTRIN_MACROVALUESTR(x)    INTRIN_MACTOSTR(x)
    #if defined(__ICL)    // Intel C++
    #  if defined(__VERSION__)
    #    define INTRIN_COMPILER_NAME    "Intel C++ " __VERSION__
    #  elif defined(__INTEL_COMPILER_BUILD_DATE)
    #    define INTRIN_COMPILER_NAME    "Intel C++ (" INTRIN_MACROVALUESTR(__INTEL_COMPILER_BUILD_DATE) ")"
    #  else
    #    define INTRIN_COMPILER_NAME    "Intel C++"
    #  endif    // #  if defined(__VERSION__)
    #elif defined(_MSC_VER)    // Microsoft VC++
    #  if defined(_MSC_FULL_VER)
    #    define INTRIN_COMPILER_NAME    "Microsoft VC++ (" INTRIN_MACROVALUESTR(_MSC_FULL_VER) ")"
    #  elif defined(_MSC_VER)
    #    define INTRIN_COMPILER_NAME    "Microsoft VC++ (" INTRIN_MACROVALUESTR(_MSC_VER) ")"
    #  else
    #    define INTRIN_COMPILER_NAME    "Microsoft VC++"
    #  endif    // #  if defined(_MSC_FULL_VER)
    #elif defined(__GNUC__)    // GCC
    #  if defined(__CYGWIN__)
    #    define INTRIN_COMPILER_NAME    "GCC(Cygmin) " __VERSION__
    #  elif defined(__MINGW32__)
    #    define INTRIN_COMPILER_NAME    "GCC(MinGW) " __VERSION__
    #  else
    #    define INTRIN_COMPILER_NAME    "GCC " __VERSION__
    #  endif    // #  if defined(_MSC_FULL_VER)
    #else
    #  define INTRIN_COMPILER_NAME    "Unknown Compiler"
    #endif    // #if defined(__ICL)    // Intel C++
    
    // INTRIN_WORDSIZE: 目标机器的字长.
    #if PTRDIFF_MAX >= INT64_MAX
        #define INTRIN_WORDSIZE    64
    #elif PTRDIFF_MAX >= INT32_MAX
        #define INTRIN_WORDSIZE    32
    #else
        #define INTRIN_WORDSIZE    16
    #endif
    
    
    // 根据不同的编译器做不同的处理.
    #if defined(__GNUC__)    // GCC
        #if (defined(__i386__) || defined(__x86_64__) )
            // header files
            //#include <cpuid.h>    // mac下有时找不到. 于是放弃, 使用ccpuid模块会更方便.
            //#include <x86intrin.h>    // mac下有时找不到. 于是根据宏来加载头文件.
            // macros
            #ifdef __MMX__
                #define INTRIN_MMX    1
                #include <mmintrin.h>
            #endif
            #ifdef __3dNOW__
                #define INTRIN_3dNOW    1
                #include <mm3dnow.h>
            #endif
            #ifdef __SSE__
                #define INTRIN_SSE    1
                #include <xmmintrin.h>
            #endif
            #ifdef __SSE2__
                #define INTRIN_SSE2    1
                #include <emmintrin.h>
            #endif
            #ifdef __SSE3__
                #define INTRIN_SSE3    1
                #include <pmmintrin.h>
            #endif
            #ifdef __SSSE3__
                #define INTRIN_SSSE3    1
                #include <tmmintrin.h>
            #endif
            #ifdef __SSE4_1__
                #define INTRIN_SSE4_1    1
                #include <smmintrin.h>
            #endif
            #ifdef __SSE4_2__
                #define INTRIN_SSE4_2    1
                #include <nmmintrin.h>
            #endif
            #ifdef __SSE4A__
                #define INTRIN_SSE4A    1
                #include <ammintrin.h>
            #endif
            #ifdef __AES__
                #define INTRIN_AES    1
                #include <x86intrin.h>
            #endif
            #ifdef __PCLMUL__
                #define INTRIN_PCLMUL    1
                #include <x86intrin.h>
            #endif
            #ifdef __AVX__
                #define INTRIN_AVX    1
                #include <x86intrin.h>
            #endif
            #ifdef __AVX2__
                #define INTRIN_AVX2    1
                #include <x86intrin.h>
            #endif
            #ifdef __F16C__
                #define INTRIN_F16C    1
                #include <x86intrin.h>
            #endif
            #ifdef __FMA__
                #define INTRIN_FMA    1
                #include <x86intrin.h>
            #endif
            #ifdef __FMA4__
                #define INTRIN_FMA4    1
                #include <x86intrin.h>
            #endif
            #ifdef __XOP__
                #define INTRIN_XOP    1
                #include <xopintrin.h>
            #endif
            #ifdef __LWP__
                #define INTRIN_LWP    1
                #include <x86intrin.h>
            #endif
            #ifdef __RDRND__
                #define INTRIN_RDRND    1
                #include <x86intrin.h>
            #endif
            #ifdef __FSGSBASE__
                #define INTRIN_FSGSBASE    1
                #include <x86intrin.h>
            #endif
            #ifdef __POPCNT__
                #define INTRIN_POPCNT    1
                #include <popcntintrin.h>
            #endif
            #ifdef __LZCNT__
                #define INTRIN_LZCNT    1
                #include <x86intrin.h>
            #endif
            #ifdef __TBM__
                #define INTRIN_TBM    1
                #include <x86intrin.h>
            #endif
            #ifdef __BMI__
                #define INTRIN_BMI    1
                #include <x86intrin.h>
            #endif
            #ifdef __BMI2__
                #define INTRIN_BMI2    1
                #include <x86intrin.h>
            #endif
    
        #endif    //#if (defined(__i386__) || defined(__x86_64__) )
    
    #elif defined(_MSC_VER)    // MSVC
        // header files
        #if _MSC_VER >=1400    // VC2005
            #include <intrin.h>
        #endif    // #if _MSC_VER >=1400
    
        #if (defined(_M_IX86) || defined(_M_X64))
            // header files
            #if _MSC_VER >=1200    // VC6
                #include <emmintrin.h>    // MMX, SSE, SSE2
                #include <mm3dnow.h>    // 3DNow!
            #endif    // #if _MSC_VER >=1400
            #include <malloc.h>    // _mm_malloc, _mm_free.
    
            // macros
            #if _MSC_VER >=1200    // VC6
                #if defined(_M_X64) && !defined(__INTEL_COMPILER)
                    // VC编译器不支持64位下的MMX.
                #else
                    #define INTRIN_MMX    1    // mmintrin.h
                    #define INTRIN_3dNOW    1    // mm3dnow.h
                #endif
                #define INTRIN_SSE    1    // xmmintrin.h
                #define INTRIN_SSE2    1    // emmintrin.h
            #endif
            #if _MSC_VER >=1300    // VC2003
            #endif
            #if _MSC_VER >=1400    // VC2005
            #endif
            #if _MSC_VER >=1500    // VC2008
                #define INTRIN_SSE3    1    // pmmintrin.h
                #define INTRIN_SSSE3    1    // tmmintrin.h
                #define INTRIN_SSE4_1    1    // smmintrin.h
                #define INTRIN_SSE4_2    1    // nmmintrin.h
                #define INTRIN_POPCNT    1    // nmmintrin.h
                #define INTRIN_SSE4A    1    // intrin.h
                // 双下划线版. #define INTRIN_LZCNT    1    // intrin.h
            #endif
            #if _MSC_VER >=1600    // VC2010
                #define INTRIN_AES    1    // wmmintrin.h
                #define INTRIN_PCLMUL    1    // wmmintrin.h
                #define INTRIN_AVX    1    // immintrin.h
                #define INTRIN_FMA4    1    // ammintrin.h
                #define INTRIN_XOP    1    // ammintrin.h
                #define INTRIN_LWP    1    // ammintrin.h
            #endif
            #if _MSC_VER >=1700    // VC2012
                #define INTRIN_AVX2    1    // immintrin.h
                #define INTRIN_FMA    1    // immintrin.h
                #define INTRIN_F16C    1    // immintrin.h
                #define INTRIN_RDRND    1    // immintrin.h
                #define INTRIN_FSGSBASE    1    // immintrin.h
                #define INTRIN_TBM    1    // ammintrin.h
                #define INTRIN_LZCNT    1    // immintrin.h
                #define INTRIN_BMI    1    // immintrin.h
                #define INTRIN_BMI2    1    // immintrin.h
                #define INTRIN_INVPCID    1    // immintrin.h
                #define INTRIN_HLE    1    // immintrin.h
                #define INTRIN_RTM    1    // immintrin.h
            #endif
    
            // VC2008之前没有_mm_cvtss_f32
            #if _MSC_VER <1500    // VC2008
                // float _mm_cvtss_f32(__m128 _A);
                #ifndef _mm_cvtss_f32
                    #define _mm_cvtss_f32(__m128_A) ( *(float*)(void*)&(__m128_A) )
                #endif
            #endif
    
        #elif defined(_M_ARM)
            // VC2012增加了 armintr.h、arm_neon.h。其中armintr.h会被intrin.h自动引入.
    
        #endif    // #if (defined(_M_IX86) || defined(_M_X64))
        //TODO:待查证 VS配合intel C编译器时intrin函数的支持性.
    
    #else
    //#error Only supports GCC or MSVC.
    #endif    // #if defined(__GNUC__)
    
    
    #endif    // #ifndef __ZINTRIN_H_INCLUDED


    2.2 testzintrin.c

      全部代码——

    View Code
    #define __STDC_LIMIT_MACROS    1    // C99整数范围常量. [仅演示, 纯C程序可以不用, 而C++程序必须定义该宏.]
    
    #include <stdio.h>
    
    #include "zintrin.h"
    
    #define PT_MAKE_STR(x)    { #x, PT_MAKE_STR_ESC(x) }
    #define PT_MAKE_STR_ESC(x)    #x
    
    typedef struct tagMACRO_T
    {
        const char *name;
        const char *value;
    } MACRO_T;
    
    /* Intrinsics */
    const MACRO_T g_intrins[] =
    {
        {"[Intrinsics]", ""},
    
    #ifdef INTRIN_MMX
        PT_MAKE_STR(INTRIN_MMX),
    #endif
    
    #ifdef INTRIN_3dNOW
        PT_MAKE_STR(INTRIN_3dNOW),
    #endif
    
    #ifdef INTRIN_SSE
        PT_MAKE_STR(INTRIN_SSE),
    #endif
    
    #ifdef INTRIN_SSE2
        PT_MAKE_STR(INTRIN_SSE2),
    #endif
    
    #ifdef INTRIN_SSE3
        PT_MAKE_STR(INTRIN_SSE3),
    #endif
    
    #ifdef INTRIN_SSSE3
        PT_MAKE_STR(INTRIN_SSSE3),
    #endif
    
    #ifdef INTRIN_SSE4_1
        PT_MAKE_STR(INTRIN_SSE4_1),
    #endif
    
    #ifdef INTRIN_SSE4_2
        PT_MAKE_STR(INTRIN_SSE4_2),
    #endif
    
    #ifdef INTRIN_SSE4A
        PT_MAKE_STR(INTRIN_SSE4A),
    #endif
    
    #ifdef INTRIN_AES
        PT_MAKE_STR(INTRIN_AES),
    #endif
    
    #ifdef INTRIN_PCLMUL
        PT_MAKE_STR(INTRIN_PCLMUL),
    #endif
    
    #ifdef INTRIN_AVX
        PT_MAKE_STR(INTRIN_AVX),
    #endif
    
    #ifdef INTRIN_AVX2
        PT_MAKE_STR(INTRIN_AVX2),
    #endif
    
    #ifdef INTRIN_F16C
        PT_MAKE_STR(INTRIN_F16C),
    #endif
    
    #ifdef INTRIN_FMA
        PT_MAKE_STR(INTRIN_FMA),
    #endif
    
    #ifdef INTRIN_FMA4
        PT_MAKE_STR(INTRIN_FMA4),
    #endif
    
    #ifdef INTRIN_XOP
        PT_MAKE_STR(INTRIN_XOP),
    #endif
    
    #ifdef INTRIN_LWP
        PT_MAKE_STR(INTRIN_LWP),
    #endif
    
    #ifdef INTRIN_RDRND
        PT_MAKE_STR(INTRIN_RDRND),
    #endif
    
    #ifdef INTRIN_FSGSBASE
        PT_MAKE_STR(INTRIN_FSGSBASE),
    #endif
    
    #ifdef INTRIN_POPCNT
        PT_MAKE_STR(INTRIN_POPCNT),
    #endif
    
    #ifdef INTRIN_LZCNT
        PT_MAKE_STR(INTRIN_LZCNT),
    #endif
    
    #ifdef INTRIN_TBM
        PT_MAKE_STR(INTRIN_TBM),
    #endif
    
    #ifdef INTRIN_BMI
        PT_MAKE_STR(INTRIN_BMI),
    #endif
    
    #ifdef INTRIN_BMI2
        PT_MAKE_STR(INTRIN_BMI2),
    #endif
    
    #ifdef INTRIN_INVPCID
        PT_MAKE_STR(INTRIN_INVPCID),
    #endif
    
    #ifdef INTRIN_HLE
        PT_MAKE_STR(INTRIN_HLE),
    #endif
    
    #ifdef INTRIN_RTM
        PT_MAKE_STR(INTRIN_RTM),
    #endif
    
    };
    
    
    //// 获取程序位数(被编译为多少位的代码)
    //int GetProgramBits(void)
    //{
    //    return sizeof(int*) * 8;
    //}
    
    void print_MACRO_T(const MACRO_T* pArray, int cnt)
    {
        int i;
        for( i = 0; i < cnt; ++i )
        {
            printf( "%s\t%s\n", pArray[i].name, pArray[i].value );
        }
        printf( "\n" );
    }
    
    
    int main(int argc, char* argv[])
    {
    
        printf("testzintrin v1.02 (%dbit)\n\n", INTRIN_WORDSIZE);
        printf("Compiler: %s\n", INTRIN_COMPILER_NAME);
        print_MACRO_T(g_intrins, sizeof(g_intrins)/sizeof(g_intrins[0]));
    
        // _mm_malloc
    #ifdef INTRIN_SSE
        if(1)
        {
            void* p;
            p = _mm_malloc(0x10, 0x10);
            printf("_mm_malloc:\t%ph\n", p);
            _mm_free(p);
        }
    #endif
    
        // mmx
    #ifdef INTRIN_MMX
        _mm_empty();
    #endif
    
        // 3DNow!
    #ifdef INTRIN_3dNOW
        //_m_femms();    // AMD cpu only.
    #endif
    
        // sse
    #ifdef INTRIN_SSE
        if(1)
        {
            __m128 xmm1;
            float f;
            printf("&xmm1:\t%ph\n", &xmm1);
            xmm1 = _mm_setzero_ps();    // SSE instruction: xorps
            f = _mm_cvtss_f32(xmm1);
            printf("_mm_cvtss_f32:\t%f\n", f);
        }
    #endif
    
        // popcnt
    #ifdef INTRIN_POPCNT
        printf("popcnt(0xffffffffu):\t%u\n", _mm_popcnt_u32(0xffffffffu));
        #if INTRIN_WORDSIZE>=64
            printf("popcnt(0xffffffffffffffffull):\t%u\n", (int)_mm_popcnt_u64(0xffffffffffffffffull));
        #endif
    #endif
    
        // avx2: only Haswell+
    #ifdef INTRIN_AVX2
        if(1)
        {
            INTRIN_ALIGN(32) uint16_t buf[16];
            volatile __m256i ymm1;    // volatile是为了避免编译优化剔除下面的AVX2代码.
            printf("&ymm1:\t%ph\n", &ymm1);
            ymm1 = _mm256_setzero_si256();    // [AVX2] VPXOR. 编译优化时可能会变为 [AVX] VXORPS
            ymm1 = _mm256_add_epi16(ymm1, ymm1);    // // [AVX2] VPADDW
            _mm256_store_si256((__m256i*)buf, ymm1);    // [AVX] VMOVDQA
            printf("ymm1[0]:\t%u\n", buf[0]);
        }
    #endif
    
        return 0;
    }


    2.3 makefile

      全部代码——

    View Code
    # flags
    CC = gcc
    CFS = -Wall
    LFS = 
    
    # args
    RELEASE =0
    BITS =
    CFLAGS = -msse
    
    # [args] 生成模式. 0代表debug模式, 1代表release模式. make RELEASE=1.
    ifeq ($(RELEASE),0)
        # debug
        CFS += -g
    else
        # release
        CFS += -static -O3 -DNDEBUG
        LFS += -static
    endif
    
    # [args] 程序位数. 32代表32位程序, 64代表64位程序, 其他默认. make BITS=32.
    ifeq ($(BITS),32)
        CFS += -m32
        LFS += -m32
    else
        ifeq ($(BITS),64)
            CFS += -m64
            LFS += -m64
        else
        endif
    endif
    
    # [args] 使用 CFLAGS 添加新的参数. make CFLAGS="-mpopcnt -msse4a".
    CFS += $(CFLAGS)
    
    
    .PHONY : all clean
    
    # files
    TARGETS = testzintrin
    OBJS = testzintrin.o
    
    all : $(TARGETS)
    
    testzintrin : $(OBJS)
        $(CC) $(LFS) -o $@ $^
    
    
    testzintrin.o : testzintrin.c zintrin.h
        $(CC) $(CFS) -c $<
    
    
    clean :
        rm -f $(OBJS) $(TARGETS) $(addsuffix .exe,$(TARGETS))


    三、测试

      在以下编译器中成功编译——
    VC6:x86版。
    VC2003:x86版。
    VC2005:x86版、x64版。
    VC2010:x86版、x64版。
    VC2012:x86版、x64版。
    GCC 4.7.0(Fedora 17 x64):x86版、x64版。
    GCC 4.6.2(MinGW(20120426)):x86版。
    GCC 4.6.1(TDM-GCC(MinGW-w64)):x86版、x64版。
    llvm-gcc-4.2(Mac OS X Lion 10.7.4, Xcode 4.4.1):x86版、x64版。

      运行效果——

      出现“停止工作”对话框是正常的。表示编译器已经正常的生成了AVX2代码,但因CPU不支持AVX2指令而抛出异常(2013的Haswell才支持AVX2)。
      可检查汇编列表文件验证这一论断。摘自“Release\testzintrin.cod”——

    ; 235  :         ymm1 = _mm256_setzero_si256();    // [AVX2] VPXOR. 编译优化时可能会变为 [AVX] VXORPS
    
      000af    c5 fc 57 c0     vxorps     ymm0, ymm0, ymm0
      000b3    c5 fd 7f 44 24
        3c         vmovdqa YMMWORD PTR _ymm1$2[esp+92], ymm0
    
    ; 236  :         ymm1 = _mm256_add_epi16(ymm1, ymm1);    // // [AVX2] VPADDW
    
      000b9    c5 fd 6f 4c 24
        3c         vmovdqa ymm1, YMMWORD PTR _ymm1$2[esp+92]
      000bf    c5 fd 6f 44 24
        3c         vmovdqa ymm0, YMMWORD PTR _ymm1$2[esp+92]
      000c5    c5 fd fd c1     vpaddw     ymm0, ymm0, ymm1
      000c9    c5 fd 7f 44 24
        3c         vmovdqa YMMWORD PTR _ymm1$2[esp+92], ymm0
    
    ; 237  :         _mm256_store_si256((__m256i*)buf, ymm1);    // [AVX] VMOVDQA
    
      000cf    c5 fd 6f 44 24
        3c         vmovdqa ymm0, YMMWORD PTR _ymm1$2[esp+92]

    参考文献——
    《ISO/IEC 9899:1999 (C99)》。ISO/IEC,1999。www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
    《Predefined Macros》. http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.110).aspx
    《[GCC] The C Preprocessor》中的《3.7.2 Common Predefined Macros》. GNU, 2011. http://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html
    《兼容C99标准的stdint.h》. http://www.cnblogs.com/zyl910/archive/2012/08/08/c99int.html
    《Intrinsics头文件与SIMD指令集、Visual Studio版本对应表》. http://www.cnblogs.com/zyl910/archive/2012/02/28/vs_intrin_table.html
    《GCC中的Intrinsics头文件与SIMD指令集、宏、参数的对应表》. http://www.cnblogs.com/zyl910/archive/2012/08/27/intrin_table_gcc.html
    《检查了一下VC2012新增的Intrinsics函数集,发现它支持ARM指令和Haswell新指令》. http://www.cnblogs.com/zyl910/archive/2012/11/06/intrin_vc2012.html
    《[C] zintrin.h : 智能引入intrinsic函数。支持VC、GCC,兼容Windows、Linux、Mac OS X》. http://www.cnblogs.com/zyl910/archive/2012/09/23/zintrin.html
    《[C] zintrin.h: 智能引入intrinsic函数 V1.01版。改进对Mac OS X的支持,增加INTRIN_WORDSIZE宏》. http://www.cnblogs.com/zyl910/archive/2012/10/01/zintrin_v101.html

    源码下载——
    https://files.cnblogs.com/zyl910/zintrin_v102.rar

    作者:zyl910
    版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0.
  • 相关阅读:
    手把手教你用Python模拟登录淘宝
    数据库链接方式ORM
    ubuntu命令
    django项目不能运行解决方法
    区别比较 match和search
    redis持久化RDB与AOF
    python基础数据类型
    python基础二
    Python中将一个对象倒序输出的4种方法
    python基础数据类型补充以及编码的进阶
  • 原文地址:https://www.cnblogs.com/zyl910/p/zintrin_v102.html
Copyright © 2011-2022 走看看