你好。这是Visual C++的UE编写者Dylan Birtolo。这是我的第一篇博客,但希望我能成为一个经常性的贡献者。我最近的一项任务是将所有新的内在函数的文档合并到visualstudio2008forvc++。自从添加了对100多个内部函数的支持以来,这是非常令人兴奋的。
在讨论intrinsic本身之前,重要的一点是,如果可以使用内联汇编(inlineassembly,inlineasm)直接访问指令,那么您为什么更喜欢使用intrinsic。以下是考虑使用内部函数的一些原因:
- 在64位机器上,Visual C++不支持内联ASM。因此,如果希望代码与64位兼容,就需要使用内部函数。
- 易用性。intrinsic不要求您知道寄存器或直接管理内存。相反,您拥有一个包含输入和返回值的完整函数。这使得更广泛的专业技术人员可以更容易地使用说明书。
- 在编译器中更新内部函数。从用户的角度来看,这意味着如果编译器改进了它处理内部函数的方式,您将立即获得这种好处。否则,如果您使用的是内联asm,您将负责进行任何改进。
- 优化器不能很好地处理内联asm代码,因此建议您在其自己的函数中编写内联asm代码,将其组装并链接。对于intrinsic,这些额外的步骤是不必要的。
- 与使用内联asm的代码相比,内部函数的可移植性更强。
现在让我们回到新的内在论。这些函数在很大程度上支持补充的数据流单指令多数据扩展指令集3(SSSE3)、数据流单指令多数据扩展指令集4.1(SSE4.1)、SSE4.2和SSE4A内部函数。还创建了一些指令来支持早期芯片组上不可用的高级位操作指令。所有这些新的内部函数首先由英特尔的Penryn和Nehalem架构以及AMD的第三代AMD Opteron处理器支持。但是,无论处理器是什么,在尝试使用给定的内在函数之前,都应该验证它是否受支持。不这样做可能会导致运行时错误。
为方便此验证过程,已更新CPUID指令。Visual Studio 2008文档的最新副本在主题cpuid中包含一个示例程序,您可以复制、编译和使用该程序。它目前是最新的,并以纯文本打印出处理器支持的技术。
所有的内部函数都很简单,都有文档和代码示例。看一看。新内部函数的表格可在以下三个主题中找到:SSE4A和高级位操作内部函数、数据流单指令多数据扩展指令集4指令和补充数据流单指令多数据扩展指令集3指令。
下面是一个新的内部函数列表,按它们支持的指令组织。有些指令非常相似,只是根据输入参数的大小而有所不同。为了节省空间,这些说明列在一起。一个需要特别考虑的不寻常的例子是POPCNT。这列在SSE4.2和ABM下。这使得内部函数与AMD和Intel编译器都兼容。
-
深交所
- CVTSI2SS–将64位有符号整数转换为浮点值,并将其插入128位参数。本质: mmu cvtsi64u ss
- CVTSS2SI–提取32位浮点值并将其舍入为64位整数。内在的: mmu cvtssu si64
- CVTTSS2SI–提取32位浮点值并将其截断为64位整数。本质: mmu cvttssu si64
- SSE2型
- CVTSD2SI–提取最低的64位浮点值并将其舍入为整数。本质: mmu cvtsdu si64
- CVTSI2SD–提取最低的64位整数并将其转换为浮点值。本质: mmu cvtsi64u sd
- CVTTSD2SI–提取64位浮点值并将其截断为64位整数。内在的:\u mmu cvttsdu si64
- MOVNTI–将64位写入指定的内存位置。本质: mmu streamu si64
- MOVQ–将64位整数移到128位参数或从128位参数移到64位整数。本质: mmu cvtsi64u si128, mmu cvtsi128u si64
- SSSE3号
- PABSB/PABSW/PABSD–获取有符号整数的绝对值。内在的: mmu absu epi8、 mmu absu epi16、 mmu absu epi32、 mmu absu pi8、 mmu absu pi16、 mmu absu pi32
- PALIGNR–组合两个参数并将结果右移。内部参数: mmu aligneru epi8, mmu aligneru pi8
- PHADDSW–添加两个包含16位有符号整数的参数,将结果饱和为16位的最大值。本质: mmu haddsu epi16, mmu haddsu pi16
- PHADDW/PHADDD–添加两个包含有符号整数的参数。内在的:\u mmu haddu epi16,\u mmu haddu epi32,\u mmu haddu pi16,\u mmu haddu pi32
- PHSUBSW–减去包含16位有符号整数的两个参数,将结果饱和为16位的最大值。内在的: mmu hsubsu epi16, mmu shubsu pi16
- PHSUBW/PHSUBD–减去两个包含有符号整数的参数。内在的: mmu hsubu epi16, mmu hsubu epi32, mmu hsubu pi16, mmu hsubu pi32
- PMADDUBSW–将8位整数相乘和相加。本质: mmu maddubsu epi16, mmu maddubsu pi16
- PMULHRSW–将16位有符号整数相乘,结果右移。内在的: mmu mulhrsu epi16, mmu mulhrsu pi16
- PSHUFB–从128位参数中选择并洗牌8位块。内在的: mmu shuffleu epi8, mmu shuffleu pi8
- PSIGNB/PSIGNW/PSIGND–取反、置零或保留有符号整数。内在语: mmu signu epi8、 mmu signu epi16、 mmu signu epi32、 mmu signu pi8、 mmu signu pi16、 mmu signu pi32
- SSE4A级
- EXTRQ–从参数中提取指定的位。内在的:\u mmu extractu si64,\u mmu extractiu si64
- INSERTQ–将指定的位插入到给定的参数中。内部代码: mmu insertu si64, mmu insertiu si64
- MOVNTSD/MOVNTSS–直接将位写入指定的内存位置,而不会污染缓存。内在的: mmu streamu sd, mmu streamu ss
- 第4.1节
- DPPD/DPPS–计算两个参数的点积。内在的: mmu dpu pd, mmu dpu ps
- EXTRACTPS–从参数中提取指定的32位浮点值。本质: mmu extractu ps
- INSERTPS–在128位参数中插入32位整数,并可能将某些位归零。本质: mmu insertu ps
- MOVNTDQA–从指定的内存位置加载128位数据。内部函数: mm u流 u加载u si128
- MPSADBW–计算八个绝对差的偏移和。内部代码: mmu mpsadbwu epu8
- PACKUSDW–使用16位饱和将32位有符号整数转换为16位有符号整数。内在的: mm u packus u epi32
- PBLENDW/BLENDPD/BLENDPS/PBLENDVB/BLENDVPD/BLENDVPS–将两个参数混合到不同的块大小中。内在成分: mmu blendu epi16、 mmu blendu pd、 mmu blendu ps、 mmu blendvu epi8、 mmu blendvu pd、 mmu blendvu ps
- PCMPEQQ–比较64位整数是否相等。内在因素:\u mmu cmpequ epi64
- PEXTRB/PEXTRW/PEXTRD/PEXTRQ–从输入参数中提取整数。内在的: mmu extract u epi8、 mmu extract u epi16、 mmu extract u epi32、 mmu extract u epi64
- PHMINPOSUW–选择最小的16位无符号整数并确定其索引。本质: mmu minposu epu16
- PINSRB/PINSRD/PINSRQ–将整数插入128位参数。内部代码: mmu insert u epi8、 mmu insert u epi32、 mmu insert u epi64
- PMAXSB/PMAXSD–从两个参数中获取有符号整数并选择最大值。本质: mmu maxu epi8, mmu maxu epi32
- PMAXUW/PMAXUD–从两个参数中获取无符号整数并选择最大值。内部参数: mmu maxu epu16、 mmu maxu epu32
- PMINSB/PMINSD–从两个参数中获取有符号整数并选择最小值。内在的: mmu minu epi8, mmu minu epi32
- PMINUW/PMINUD–从两个参数中获取无符号整数并选择最小值。内在的: mmu minu epu16, mmu minu epu32
- PMOVSXBW/PMOVSXBD/PMOVSXBQ/PMOVSXWD/PMOVSXWQ/PMOVSXDQ–将一个大小的有符号整数转换为更大的大小。内在因素: mmu cvtepi8 u epi16、 mmu cvtepi8 u epi32、 mmu cvtepi8 u epi64、 mmu cvtepi16 u epi32、 mmu cvtepi16 u epi64、 mmu cvtepi32 u epi64
- PMOVZXBW/PMOVZXBD/PMOVZXBQ/PMOVZXWD/PMOVZXWQ/PMOVZXDQ–将一个大小的无符号整数转换为更大的大小。内部函数: mmu cvtepu8 u epi16、 mmu cvtepu8 u epi32、 mmu cvtepu8 u epi64、 mmu cvtepu16 u epi32、 mmu cvtepu16 u epi64、 mmu cvtepu32 u epi64
- PMULDQ–将32位有符号整数相乘,并将结果存储为64位有符号整数。内在的: mmu mulu epi32
- PMULLUD–将32位有符号整数相乘。内在的: mmu mullou epi32
- PTEST–计算两个128位参数的逐位测试,并基于CC标志寄存器的CF和ZF位返回值。内部参数: mmu testcu si128¸ _mmu testnzcu si128,u mmu testzu si128
- ROUNDPD/ROUNDPS–舍入浮点值。内在的: mmu ceilu pd, mmu ceilu ps, mmu flooru pd, mmu flooru ps, mmu roundu pd, mmu roundu ps
- ROUNDSD/ROUNDSS–组合两个参数,从其中一个参数取整浮点值。内在的: mmu ceilu sd, mmu ceilu ss, mmu flooru sd, mmu flooru ss, mmu roundu sd, mmu roundu ss
- 第4.2节
- CRC32–计算参数的CRC-32C校验和。本质: mmu crc32u u8¸ _毫米crc32毫米u16,毫米crc32毫米u32,毫米crc32毫米u64
- PCMPESTRI/PCMPESTRM–比较指定长度的两个参数。内在论:\u mmu cmpestra,\u mmu cmpestrc,\u mmu cmpestri,\u mmu cmpestrm,\u mmu cmpestro,\u mmu cmpestrs,\u mmu cmpestrz
- PCMPGTQ–比较两个参数。内在因素:\u mmu cmpgtu epi64
- PCMPISTRI/PCMPISTRM–比较两个参数。内在的:\u mmu cmpistra,\u mmu cmpistrc,\u mmu cmpistri,\u mmu cmpistrm,\u mmu cmpistro,\u mmu cmpistrs,\u mmu cmpistrz
- POPCNT–统计设置为1的位数。内部参数: mmu POPCNTu u32、 mmu POPCNTu u64、 u popcnt16、 u POPCNT、 u popcnt64
- 高级位操作
- LZCNT–计算参数开头的零数。内在的:uuuzcnt16,uuzcnt,uuuzcnt64
- POPCNT–统计设置为1的位数。内部参数: mmu POPCNTu u32、 mmu POPCNTu u64、 u popcnt16、 u POPCNT、 u popcnt64
- 其他新本质
- _InterlockedCompareExchange 128–比较两个参数。
- _mmu castpd u ps/u mmu castpd u si128/u mmu castps u pd/u mmu castps u si128/u mmu castsi128 u pd/u mmu castsi128 u ps–在32位浮点值(ps)、64位浮点值(pd)和32位整数(si128)之间重新解释。
- _mm_cvtsd_f64–从参数中提取最低的64位浮点值。
- _mmu cvtssu f32–提取32位浮点值。
- _rdtscp–生成rdtscp。将TSC AUX[31:0]写入内存并返回64位时间戳计数器结果。