CPUID
通过使用CPUID指令、检查控制寄存器位和读取特定型号的寄存器来获取特征标志、状态和系统信息。
表1-1 CPU识别
操作码 | 指令 | Op/En | 64位模式 | 兼容/传统模式 | 描述 |
---|---|---|---|---|---|
OF A2 | CPUID | Z0 | 有效 | 有效 | 将处理器标识和特征信息返回到EAX、EBX、ECX和EDX寄存器,由输入EAX决定(在某些情况下,ECX也可以) |
表1-2 指令操作数编码
Op/En | 操作码1 | 操作码2 | 操作码3 | 操作码4 |
---|---|---|---|---|
Z0 | N/A | N/A | N/A | N/A |
表1-3 CPUID指令提供的信息
输入EAX的值 | 处理器提供的信息 |
---|---|
0H | EAX CPUID基本信息最大输入值 EBX "Genu" ECX "ntel" EDX "inel" |
1H | EAX 版本信息:类型,家族,型号,步进ID EBX 07-00:品牌索引(brand index) 15-08:CLFLUSH行大小(value*8=缓存行大小,字节为单位,CLFLUSHOPT也使用) 23-16:物理包中逻辑处理器的最大地址ID 31-24:初始高级可编程中断控制器(APIC)ID ECX 特征信息 EDX 特征信息 |
详:见官方手册。
SIMD
AVX指令使用一种编码方案进行编码,该方案将前缀字节、操作码扩展字段、操作数编码字段和向量长度编码能力组合成一个新的前缀,称为VEX。在VEX编码方案中,VEX前缀可能是2或3个字节长,这取决于指令语义。
SSE和AVX指令包含若干变体:原始SSE、增强SSE2、SSE3、SSE4(SSE4.1和SSE4.2)、AVX、AVX2以及-AVX512。SSE3是与Pentium 4F(Prescoot)CPU同时推出的。
SSE和AVX体系结构指令主要有如下三代:
-
SSE体系结构,提供16个128位的XMM寄存器,支持整数和浮点数据类型
-
AVX/AVX2结构,支持16个256位的YMM寄存器
-
AVX-512,支持多达32个512位的ZMM寄存器
图1-1 AVX-512寄存器图
检测AVX指令
在使用AVX之前,应用程序必须确定操作系统支持XGETBV指令、YMM寄存器状态,以及处理器支持使用XSAVE/XRSTOR和XRSTOR进行YMM状态管理AVX指令。步骤如下:
-
检查CPUID.1:ECX.OSXSAVE[bit 27] = 1 (启用XGETBV给应用程序使用)
-
执行XGETBV并验证 XCR0[2:1] = '11b'(xmm和ymm状态由操作系统启用)
-
检查CPUID.1:ECX.AVX[bit 28] = 1 (支持AVX指令)
步骤3可以按照相对于1和2的任何顺序进行。
其它指令集检测见官方手册。
图1-2 xcr0寄存器
内存对齐
SIMDData segment align(64)
sseData oword 0 ;64字节对齐
align 32 ;对AVX数据进行对齐
avxData oword 0,1 ;32字节对齐
align 64
avx2Data oword 0,1,2,3,4
SIMDData ends
使用segment和ends伪指令创建段,用align(n)对齐,n必须为2的次幂。
注意:对于试图访问未对齐到16字节的地址处的128位数据对象,几乎所有的SSE、AVX和AVX2指令都会生成内存对齐故障。应该始终确保SSE打包操作数要合理对齐。
SIMD指令
SIMD数据移动:
-
(v)movd、(v)movq
movd xmmn,reg32/mem32
movd reg32/mem32,xmmn
movq xmmn,reg64/mem64
movq reg64/mem64,xmmn
movq xmmn,xmmn
-
(v)movaps、(v)movapd、(v)movdqa 移动对齐打包单(双)精度、四字节对齐值
movaps xmmn,mem128
movaps xmmn,xmmn
vmovaps xmmn,mem128
vmovaps xmmn,xmmn
vmovaps ymmn,mem256
vmovaps ymmn,ymmn
-
(v)movups、(v)movupd、(v)movdqu 移动未对齐打包单(双)精度、四字节值
-
(v)movlps、(v)movlpd 移动低阶数据
-
movhps、movhpd 移动高阶数据
-
vmovhps、vmovhpd
vmovhps xmm(dest),xmm(src),mem64 ;高阶来自内存,低阶来自xmm寄存器
vmovhps xmm(dest),xmm(src)
vmovhpd xmm(dest),xmm(src),mem64
vmovhpd xmm(dest),xmm(src)
-
(v)movlhps 将低阶复制到高阶
movlhps xmm(dest),xmm(src)
vmovlhps xmm(dest),xmm(src),xmm(src2)
-
(v)movhlps 将高阶复制到低阶
-
(v)movshdup、(v)movsldup 移动奇(偶)索引并复制到xmm或ymm寄存器中
图1-3 movshdup
-
(v)movddup 将低阶或内存单元复制到xmm或ymm寄存器中,并复制到高位
图1-4 movddup
-
(v)lddqu 操作与(v)movdqu相同
混排解包:略。
逻辑运算:
-
(v)andpd、(v)andndp
andpd xmm(dest),xmm(src)/mem128
vandpd xmm(dest),xmm(src1),xmm(src2),mem128
vandpd ymm(dest),ymm(src1),ymm(src2),mem256
-
(v)orpd
-
(v)xorpd
打包测试:(v)ptest
字节移位指令:
-
(v)pslldq
-
(v)psrldq
位移位指令:(v)shift
SIMD整数加法:
-
(v)paddb、(v)paddw、(v)paddd、(v)paddq
paddb xmm(dest),xmm/mem128
vpaddb xmm(dest),xmm(src1),xmm(src2)/mem128
vpaddb ymm(dest),ymm(src1),ymm(src2)/mem256
-
(v)paddsb、(V)paddsw、(v)paddusb、(v)paddusw 饱和加法
整数水平运算:略。
SIMD整数减法:
-
(v)psubb、(v)psubw、(v)psubd、(v)psubq
psubb xmm(dest),xmm/mem128
vpsubb xmm(dest),xmm(src1),xmm(src2)/mem128
vpsubb ymm(dest),ymm(src1),ymm(src2)/mem256
-
(v)psubsb、(V)psubsw、(v)psubusb、(v)psubusw 饱和减法
SIMD整数乘法:
-
(v)pmullw、(v)pmulhuw、(v)pmulhw
pmullw xmm(dest),xmm/mem128
vpmullw xmm(dest),xmm(src1),xmm(src2)/mem128
vpmullw ymm(dest),ymm(src1),ymm(src2)/mem256
-
(v)pmulld、(v)pmullq
-
(v)pmuldq、(v)pmuludq
-
(v)pclmulqdq
SIMD整数平均值:(v)pavgb、(v)pavgw
SIMD最大最小值:略。
SIMD整数绝对值:(v)pabsb、(v)pabsw、(v)pabsd
SIMD整数符号调整:(v)psignb、(v)psignw、(v)psignd
SIMD整数比较:
-
(v)pcmpeqb、(v)pcmpeqw、(v)pcmpeqd、(v)pcmpeqq
-
(v)pcmpgtb、(v)pcmpgtw、(v)pcmpgtd、(v)pcmpgtq
整数转换:略
SIMD浮点算数指令:
-
(v)addps、(v)addpd
-
(v)subps、(v)subpd
-
(v)mulps、(v)mulpd
-
(v)divps、(v)divpd
-
(v)maxps、(v)maxpd
-
(v)minps、(v)minpd
-
(v)sqrtps、(v)sqrtpd
- (v)rsqrtps
浮点水平运算:略。
SSE和AVX比较指令:(v)cmpps、(v)cmppd
cmpps xmm(dest),xmm(src)/mem128,imm8
vcmpps xmm(dest),xmm(src1),xmm(src2)/mem128,imm8
vcmpps ymm(dest),ymm(src1),ymm(src2)/mem256,imm8
AVX扩展比较:vcmpps、vcmppd
SIMD比较指令:(v)movmskps、(v)movmskpd
movmskps reg,xmm(src)
vmovmskps reg,ymm(src)
浮点转换指令:略。
参数传递和返回值
表1-4 参数传递
参数类型 | 第 5 个和更高位置 | 第 4 个 | 第3 个 | second | 最左侧 |
---|---|---|---|---|---|
浮点 | 堆栈 | XMM3 | XMM2 | XMM1 | XMM0 |
整型 | 堆栈 | R9 | R8 | RDX | RCX |
聚合(8、16、32 或 64 位)和 __m64 | 堆栈 | R9 | R8 | RDX | RCX |
其他聚合,作为指针 | 堆栈 | R9 | R8 | RDX | RCX |
__m128 ,作为指针 | 堆栈 | R9 | R8 | RDX | RCX |
可以适应 64 位的标量返回值(包括 __m64
类型)是通过 RAX 返回的。 非标量类型(包括浮点类型、双精度类型和向量类型,例如 __m128、__m128i、__m128d)以 XMM0 的形式返回。 返回到 RAX 或 XMM0 中的值的未使用位数的状态未定义。
推测:AVX传递使用RCX,RDX,R8,R9和堆栈,返回值使用YMM0。AVX-512返回使用ZMM0。
代码
cpp
//main.cpp
#include<iostream>
#include<stdio.h>
#include<intrin.h>
using namespace std;
extern "C"{
int checkavx(void);
char* cpuid0(int& maxFeature);
__m256d dadd(__m256d a,__m256d b);
}
void print(__m256d md){
for(int i=0;i<4;i++){
cout<<md.m256d_f64[i]<<"\t";
}
cout<<endl;
}
int main(){
if(checkavx()!=1){
cout<<"not Support avx"<<endl;
return 0;
}
char* vendorId=nullptr;
__m256d a={{1.1,2.2,3.3,4.4}},b={{5.5,6.6,7.7,8.8}},c;
int maxFeature=0;
vendorId=cpuid0(maxFeature);
printf("CPUID(0): Vendor ID='%s', max feature=%d\n",vendorId,maxFeature);
c=dadd(a,b);
print(c);
c=_mm256_mul_pd(a,b);
print(c);
c=_mm256_movedup_pd(a);
print(c);
c=_mm256_sqrt_pd(b);
print(c);
return 0;
}
asm
;avx.asm
option casemap:none
.data
VendorID byte 14 dup (0)
.code
public checkavx
checkavx proc
mov eax,1
cpuid
and ecx,018000000h
cmp ecx,018000000h
jne notSupport
mov ecx,0
xgetbv
and eax,06h
cmp eax,06h
jne notSupport
mov eax,1
jmp done
notSupport:
mov eax,0
done:
ret
checkavx endp
public cpuid0
cpuid0 proc
push rbp
mov rbp,rsp
push rcx
xor eax,eax
cpuid
mov r8,[rsp]
mov [r8],eax
mov dword ptr VendorID, ebx
mov dword ptr VendorID[4], edx
mov dword ptr VendorID[8], ecx
mov eax,offset VendorID
leave
ret
cpuid0 endp
public dadd
dadd proc
vmovaps ymm1,[rcx]
vmovaps ymm2,[rdx]
vaddpd ymm0,ymm1,ymm2
ret
dadd endp
end
扩展资料
-
x86/x64 SIMD Instruction List (SSE to AVX512) (officedaytime.com)
-
A Novel Hybrid Quicksort Algorithm Vectorized using AVX-512 on Intel Skylake
-
Register level sort algorithm on multi-core SIMD processors
-
Fast Quicksort Implementation Using AVX Instructions
-
SIMD-friendly algorithms for substring searching
-
Fast Quicksort Implementation Using AVX Instructions
-
k-Ary Search on Modern Processors
参考
-
[美]兰德尔·海德.64位汇编语言的编程艺术
-
Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4
-
AMD64 Architecture Programmer’s Manual Volumes 1–5