func (f flags) String() string {
	return strings.Join(f.strings(), ",")
}
String returns a string representation of the detected
CPU features.
package cpuid
import (
	"strings"
)
type vendor int
const (
	other	vendor	= iota
	intel
	amd
	via
	transmeta
	nsc
	kvm	 
	msvm	 
	vmware
	xenhvm
)
const (
	cmov		= 1 << iota	 
	nx				 
	amd3dnow			 
	amd3dnowext			 
	mmx				 
	mmxext				 
	sse				 
	sse2				 
	sse3				 
	ssse3				 
	sse4				 
	sse4a				 
	sse42				 
	avx				 
	avx2				 
	fma3				 
	fma4				 
	xop				 
	f16c				 
	bmi1				 
	bmi2				 
	tbm				 
	lzcnt				 
	popcnt				 
	aesni				 
	clmul				 
	htt				 
	hle				 
	rtm				 
	rdrand				 
	rdseed				 
	adx				 
	sha				 
	avx512f				 
	avx512dq			 
	avx512ifma			 
	avx512pf			 
	avx512er			 
	avx512cd			 
	avx512bw			 
	avx512vl			 
	avx512vbmi			 
	mpx				 
	erms				 
	rdtscp				 
	cx16				 
	sse2slow	 
	sse3slow	 
	atom		 
)
var flagNames = map[flags]string{
	cmov:		"CMOV",		 
	nx:		"NX",		 
	amd3dnow:	"AMD3DNOW",	 
	amd3dnowext:	"AMD3DNOWEXT",	 
	mmx:		"MMX",		 
	mmxext:		"MMXEXT",	 
	sse:		"SSE",		 
	sse2:		"SSE2",		 
	sse3:		"SSE3",		 
	ssse3:		"SSSE3",	 
	sse4:		"SSE4.1",	 
	sse4a:		"SSE4A",	 
	sse42:		"SSE4.2",	 
	avx:		"AVX",		 
	avx2:		"AVX2",		 
	fma3:		"FMA3",		 
	fma4:		"FMA4",		 
	xop:		"XOP",		 
	f16c:		"F16C",		 
	bmi1:		"BMI1",		 
	bmi2:		"BMI2",		 
	tbm:		"TBM",		 
	lzcnt:		"LZCNT",	 
	popcnt:		"POPCNT",	 
	aesni:		"AESNI",	 
	clmul:		"CLMUL",	 
	htt:		"HTT",		 
	hle:		"HLE",		 
	rtm:		"RTM",		 
	rdrand:		"RDRAND",	 
	rdseed:		"RDSEED",	 
	adx:		"ADX",		 
	sha:		"SHA",		 
	avx512f:	"AVX512F",	 
	avx512dq:	"AVX512DQ",	 
	avx512ifma:	"AVX512IFMA",	 
	avx512pf:	"AVX512PF",	 
	avx512er:	"AVX512ER",	 
	avx512cd:	"AVX512CD",	 
	avx512bw:	"AVX512BW",	 
	avx512vl:	"AVX512VL",	 
	avx512vbmi:	"AVX512VBMI",	 
	mpx:		"MPX",		 
	erms:		"ERMS",		 
	rdtscp:		"RDTSCP",	 
	cx16:		"CX16",		 
	sse2slow:	"SSE2SLOW",	 
	sse3slow:	"SSE3SLOW",	 
	atom:		"ATOM",		 
}
type cpuInfo struct {
	brandname	string	 
	vendorid	vendor	 
	features	flags	 
	physicalcores	int	 
	threadspercore	int	 
	logicalcores	int	 
	family		int	 
	model		int	 
	cacheline	int	 
	cache		struct {
		l1i	int	 
		l1d	int	 
		l2	int	 
		l3	int	 
	}
	maxFunc		uint32
	maxExFunc	uint32
}
var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
var cpuidex func(op, op2 uint32) (eax, ebx, ecx, edx uint32)
var xgetbv func(index uint32) (eax, edx uint32)
var rdtscpAsm func() (eax, ebx, ecx, edx uint32)
var cpu cpuInfo
func init() {
	initCPU()
	detect()
}
func detect() {
	cpu.maxFunc = maxFunctionID()
	cpu.maxExFunc = maxExtendedFunction()
	cpu.brandname = brandName()
	cpu.cacheline = cacheLine()
	cpu.family, cpu.model = familyModel()
	cpu.features = support()
	cpu.threadspercore = threadsPerCore()
	cpu.logicalcores = logicalCores()
	cpu.physicalcores = physicalCores()
	cpu.vendorid = vendorID()
	cpu.cacheSize()
}
func (c cpuInfo) cmov() bool {
	return c.features&cmov != 0
}
func (c cpuInfo) amd3dnow() bool {
	return c.features&amd3dnow != 0
}
func (c cpuInfo) amd3dnowext() bool {
	return c.features&amd3dnowext != 0
}
func (c cpuInfo) mmx() bool {
	return c.features&mmx != 0
}
func (c cpuInfo) mmxext() bool {
	return c.features&mmxext != 0
}
func (c cpuInfo) sse() bool {
	return c.features&sse != 0
}
func (c cpuInfo) sse2() bool {
	return c.features&sse2 != 0
}
func (c cpuInfo) sse3() bool {
	return c.features&sse3 != 0
}
func (c cpuInfo) ssse3() bool {
	return c.features&ssse3 != 0
}
func (c cpuInfo) sse4() bool {
	return c.features&sse4 != 0
}
func (c cpuInfo) sse42() bool {
	return c.features&sse42 != 0
}
func (c cpuInfo) avx() bool {
	return c.features&avx != 0
}
func (c cpuInfo) avx2() bool {
	return c.features&avx2 != 0
}
func (c cpuInfo) fma3() bool {
	return c.features&fma3 != 0
}
func (c cpuInfo) fma4() bool {
	return c.features&fma4 != 0
}
func (c cpuInfo) xop() bool {
	return c.features&xop != 0
}
func (c cpuInfo) f16c() bool {
	return c.features&f16c != 0
}
func (c cpuInfo) bmi1() bool {
	return c.features&bmi1 != 0
}
func (c cpuInfo) bmi2() bool {
	return c.features&bmi2 != 0
}
func (c cpuInfo) tbm() bool {
	return c.features&tbm != 0
}
func (c cpuInfo) lzcnt() bool {
	return c.features&lzcnt != 0
}
func (c cpuInfo) popcnt() bool {
	return c.features&popcnt != 0
}
func (c cpuInfo) htt() bool {
	return c.features&htt != 0
}
func (c cpuInfo) sse2slow() bool {
	return c.features&sse2slow != 0
}
func (c cpuInfo) sse3slow() bool {
	return c.features&sse3slow != 0
}
func (c cpuInfo) aesni() bool {
	return c.features&aesni != 0
}
func (c cpuInfo) clmul() bool {
	return c.features&clmul != 0
}
func (c cpuInfo) nx() bool {
	return c.features&nx != 0
}
func (c cpuInfo) sse4a() bool {
	return c.features&sse4a != 0
}
func (c cpuInfo) hle() bool {
	return c.features&hle != 0
}
func (c cpuInfo) rtm() bool {
	return c.features&rtm != 0
}
func (c cpuInfo) rdrand() bool {
	return c.features&rdrand != 0
}
func (c cpuInfo) rdseed() bool {
	return c.features&rdseed != 0
}
func (c cpuInfo) adx() bool {
	return c.features&adx != 0
}
func (c cpuInfo) sha() bool {
	return c.features&sha != 0
}
func (c cpuInfo) avx512f() bool {
	return c.features&avx512f != 0
}
func (c cpuInfo) avx512dq() bool {
	return c.features&avx512dq != 0
}
func (c cpuInfo) avx512ifma() bool {
	return c.features&avx512ifma != 0
}
func (c cpuInfo) avx512pf() bool {
	return c.features&avx512pf != 0
}
func (c cpuInfo) avx512er() bool {
	return c.features&avx512er != 0
}
func (c cpuInfo) avx512cd() bool {
	return c.features&avx512cd != 0
}
func (c cpuInfo) avx512bw() bool {
	return c.features&avx512bw != 0
}
func (c cpuInfo) avx512vl() bool {
	return c.features&avx512vl != 0
}
func (c cpuInfo) avx512vbmi() bool {
	return c.features&avx512vbmi != 0
}
func (c cpuInfo) mpx() bool {
	return c.features&mpx != 0
}
func (c cpuInfo) erms() bool {
	return c.features&erms != 0
}
func (c cpuInfo) rdtscp() bool {
	return c.features&rdtscp != 0
}
func (c cpuInfo) cx16() bool {
	return c.features&cx16 != 0
}
func (c cpuInfo) atom() bool {
	return c.features&atom != 0
}
func (c cpuInfo) intel() bool {
	return c.vendorid == intel
}
func (c cpuInfo) amd() bool {
	return c.vendorid == amd
}
func (c cpuInfo) transmeta() bool {
	return c.vendorid == transmeta
}
func (c cpuInfo) nsc() bool {
	return c.vendorid == nsc
}
func (c cpuInfo) via() bool {
	return c.vendorid == via
}
func (c cpuInfo) rtcounter() uint64 {
	if !c.rdtscp() {
		return 0
	}
	a, _, _, d := rdtscpAsm()
	return uint64(a) | (uint64(d) << 32)
}
func (c cpuInfo) ia32tscaux() uint32 {
	if !c.rdtscp() {
		return 0
	}
	_, _, ecx, _ := rdtscpAsm()
	return ecx
}
func (c cpuInfo) logicalcpu() int {
	if c.maxFunc < 1 {
		return -1
	}
	_, ebx, _, _ := cpuid(1)
	return int(ebx >> 24)
}
func (c cpuInfo) vm() bool {
	switch c.vendorid {
	case msvm, kvm, vmware, xenhvm:
		return true
	}
	return false
}
type flags uint64