1// Generated, DO NOT EDIT,
2// but copy it to your own project and rename the package.
3// See more at http://github.com/klauspost/cpuid
4
5package cpuid
6
7import (
8	"math"
9	"strings"
10)
11
12// AMD refererence: https://www.amd.com/system/files/TechDocs/25481.pdf
13// and Processor Programming Reference (PPR)
14
15// Vendor is a representation of a CPU vendor.
16type vendor int
17
18const (
19	other vendor = iota
20	intel
21	amd
22	via
23	transmeta
24	nsc
25	kvm  // Kernel-based Virtual Machine
26	msvm // Microsoft Hyper-V or Windows Virtual PC
27	vmware
28	xenhvm
29	bhyve
30	hygon
31	sis
32	rdc
33)
34
35const (
36	cmov               = 1 << iota // i686 CMOV
37	nx                             // NX (No-Execute) bit
38	amd3dnow                       // AMD 3DNOW
39	amd3dnowext                    // AMD 3DNowExt
40	mmx                            // standard MMX
41	mmxext                         // SSE integer functions or AMD MMX ext
42	sse                            // SSE functions
43	sse2                           // P4 SSE functions
44	sse3                           // Prescott SSE3 functions
45	ssse3                          // Conroe SSSE3 functions
46	sse4                           // Penryn SSE4.1 functions
47	sse4a                          // AMD Barcelona microarchitecture SSE4a instructions
48	sse42                          // Nehalem SSE4.2 functions
49	avx                            // AVX functions
50	avx2                           // AVX2 functions
51	fma3                           // Intel FMA 3
52	fma4                           // Bulldozer FMA4 functions
53	xop                            // Bulldozer XOP functions
54	f16c                           // Half-precision floating-point conversion
55	bmi1                           // Bit Manipulation Instruction Set 1
56	bmi2                           // Bit Manipulation Instruction Set 2
57	tbm                            // AMD Trailing Bit Manipulation
58	lzcnt                          // LZCNT instruction
59	popcnt                         // POPCNT instruction
60	aesni                          // Advanced Encryption Standard New Instructions
61	clmul                          // Carry-less Multiplication
62	htt                            // Hyperthreading (enabled)
63	hle                            // Hardware Lock Elision
64	rtm                            // Restricted Transactional Memory
65	rdrand                         // RDRAND instruction is available
66	rdseed                         // RDSEED instruction is available
67	adx                            // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
68	sha                            // Intel SHA Extensions
69	avx512f                        // AVX-512 Foundation
70	avx512dq                       // AVX-512 Doubleword and Quadword Instructions
71	avx512ifma                     // AVX-512 Integer Fused Multiply-Add Instructions
72	avx512pf                       // AVX-512 Prefetch Instructions
73	avx512er                       // AVX-512 Exponential and Reciprocal Instructions
74	avx512cd                       // AVX-512 Conflict Detection Instructions
75	avx512bw                       // AVX-512 Byte and Word Instructions
76	avx512vl                       // AVX-512 Vector Length Extensions
77	avx512vbmi                     // AVX-512 Vector Bit Manipulation Instructions
78	avx512vbmi2                    // AVX-512 Vector Bit Manipulation Instructions, Version 2
79	avx512vnni                     // AVX-512 Vector Neural Network Instructions
80	avx512vpopcntdq                // AVX-512 Vector Population Count Doubleword and Quadword
81	gfni                           // Galois Field New Instructions
82	vaes                           // Vector AES
83	avx512bitalg                   // AVX-512 Bit Algorithms
84	vpclmulqdq                     // Carry-Less Multiplication Quadword
85	avx512bf16                     // AVX-512 BFLOAT16 Instructions
86	avx512vp2intersect             // AVX-512 Intersect for D/Q
87	mpx                            // Intel MPX (Memory Protection Extensions)
88	erms                           // Enhanced REP MOVSB/STOSB
89	rdtscp                         // RDTSCP Instruction
90	cx16                           // CMPXCHG16B Instruction
91	sgx                            // Software Guard Extensions
92	sgxlc                          // Software Guard Extensions Launch Control
93	ibpb                           // Indirect Branch Restricted Speculation (IBRS) and Indirect Branch Predictor Barrier (IBPB)
94	stibp                          // Single Thread Indirect Branch Predictors
95	vmx                            // Virtual Machine Extensions
96
97	// Performance indicators
98	sse2slow // SSE2 is supported, but usually not faster
99	sse3slow // SSE3 is supported, but usually not faster
100	atom     // Atom processor, some SSSE3 instructions are slower
101)
102
103var flagNames = map[flags]string{
104	cmov:               "CMOV",               // i686 CMOV
105	nx:                 "NX",                 // NX (No-Execute) bit
106	amd3dnow:           "AMD3DNOW",           // AMD 3DNOW
107	amd3dnowext:        "AMD3DNOWEXT",        // AMD 3DNowExt
108	mmx:                "MMX",                // Standard MMX
109	mmxext:             "MMXEXT",             // SSE integer functions or AMD MMX ext
110	sse:                "SSE",                // SSE functions
111	sse2:               "SSE2",               // P4 SSE2 functions
112	sse3:               "SSE3",               // Prescott SSE3 functions
113	ssse3:              "SSSE3",              // Conroe SSSE3 functions
114	sse4:               "SSE4.1",             // Penryn SSE4.1 functions
115	sse4a:              "SSE4A",              // AMD Barcelona microarchitecture SSE4a instructions
116	sse42:              "SSE4.2",             // Nehalem SSE4.2 functions
117	avx:                "AVX",                // AVX functions
118	avx2:               "AVX2",               // AVX functions
119	fma3:               "FMA3",               // Intel FMA 3
120	fma4:               "FMA4",               // Bulldozer FMA4 functions
121	xop:                "XOP",                // Bulldozer XOP functions
122	f16c:               "F16C",               // Half-precision floating-point conversion
123	bmi1:               "BMI1",               // Bit Manipulation Instruction Set 1
124	bmi2:               "BMI2",               // Bit Manipulation Instruction Set 2
125	tbm:                "TBM",                // AMD Trailing Bit Manipulation
126	lzcnt:              "LZCNT",              // LZCNT instruction
127	popcnt:             "POPCNT",             // POPCNT instruction
128	aesni:              "AESNI",              // Advanced Encryption Standard New Instructions
129	clmul:              "CLMUL",              // Carry-less Multiplication
130	htt:                "HTT",                // Hyperthreading (enabled)
131	hle:                "HLE",                // Hardware Lock Elision
132	rtm:                "RTM",                // Restricted Transactional Memory
133	rdrand:             "RDRAND",             // RDRAND instruction is available
134	rdseed:             "RDSEED",             // RDSEED instruction is available
135	adx:                "ADX",                // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
136	sha:                "SHA",                // Intel SHA Extensions
137	avx512f:            "AVX512F",            // AVX-512 Foundation
138	avx512dq:           "AVX512DQ",           // AVX-512 Doubleword and Quadword Instructions
139	avx512ifma:         "AVX512IFMA",         // AVX-512 Integer Fused Multiply-Add Instructions
140	avx512pf:           "AVX512PF",           // AVX-512 Prefetch Instructions
141	avx512er:           "AVX512ER",           // AVX-512 Exponential and Reciprocal Instructions
142	avx512cd:           "AVX512CD",           // AVX-512 Conflict Detection Instructions
143	avx512bw:           "AVX512BW",           // AVX-512 Byte and Word Instructions
144	avx512vl:           "AVX512VL",           // AVX-512 Vector Length Extensions
145	avx512vbmi:         "AVX512VBMI",         // AVX-512 Vector Bit Manipulation Instructions
146	avx512vbmi2:        "AVX512VBMI2",        // AVX-512 Vector Bit Manipulation Instructions, Version 2
147	avx512vnni:         "AVX512VNNI",         // AVX-512 Vector Neural Network Instructions
148	avx512vpopcntdq:    "AVX512VPOPCNTDQ",    // AVX-512 Vector Population Count Doubleword and Quadword
149	gfni:               "GFNI",               // Galois Field New Instructions
150	vaes:               "VAES",               // Vector AES
151	avx512bitalg:       "AVX512BITALG",       // AVX-512 Bit Algorithms
152	vpclmulqdq:         "VPCLMULQDQ",         // Carry-Less Multiplication Quadword
153	avx512bf16:         "AVX512BF16",         // AVX-512 BFLOAT16 Instruction
154	avx512vp2intersect: "AVX512VP2INTERSECT", // AVX-512 Intersect for D/Q
155	mpx:                "MPX",                // Intel MPX (Memory Protection Extensions)
156	erms:               "ERMS",               // Enhanced REP MOVSB/STOSB
157	rdtscp:             "RDTSCP",             // RDTSCP Instruction
158	cx16:               "CX16",               // CMPXCHG16B Instruction
159	sgx:                "SGX",                // Software Guard Extensions
160	sgxlc:              "SGXLC",              // Software Guard Extensions Launch Control
161	ibpb:               "IBPB",               // Indirect Branch Restricted Speculation and Indirect Branch Predictor Barrier
162	stibp:              "STIBP",              // Single Thread Indirect Branch Predictors
163	vmx:                "VMX",                // Virtual Machine Extensions
164
165	// Performance indicators
166	sse2slow: "SSE2SLOW", // SSE2 supported, but usually not faster
167	sse3slow: "SSE3SLOW", // SSE3 supported, but usually not faster
168	atom:     "ATOM",     // Atom processor, some SSSE3 instructions are slower
169
170}
171
172/* all special features for arm64 should be defined here */
173const (
174	/* extension instructions */
175	fp armflags = 1 << iota
176	asimd
177	evtstrm
178	aes
179	pmull
180	sha1
181	sha2
182	crc32
183	atomics
184	fphp
185	asimdhp
186	armcpuid
187	asimdrdm
188	jscvt
189	fcma
190	lrcpc
191	dcpop
192	sha3
193	sm3
194	sm4
195	asimddp
196	sha512
197	sve
198	gpa
199)
200
201var flagNamesArm = map[armflags]string{
202	fp:       "FP",       // Single-precision and double-precision floating point
203	asimd:    "ASIMD",    // Advanced SIMD
204	evtstrm:  "EVTSTRM",  // Generic timer
205	aes:      "AES",      // AES instructions
206	pmull:    "PMULL",    // Polynomial Multiply instructions (PMULL/PMULL2)
207	sha1:     "SHA1",     // SHA-1 instructions (SHA1C, etc)
208	sha2:     "SHA2",     // SHA-2 instructions (SHA256H, etc)
209	crc32:    "CRC32",    // CRC32/CRC32C instructions
210	atomics:  "ATOMICS",  // Large System Extensions (LSE)
211	fphp:     "FPHP",     // Half-precision floating point
212	asimdhp:  "ASIMDHP",  // Advanced SIMD half-precision floating point
213	armcpuid: "CPUID",    // Some CPU ID registers readable at user-level
214	asimdrdm: "ASIMDRDM", // Rounding Double Multiply Accumulate/Subtract (SQRDMLAH/SQRDMLSH)
215	jscvt:    "JSCVT",    // Javascript-style double->int convert (FJCVTZS)
216	fcma:     "FCMA",     // Floatin point complex number addition and multiplication
217	lrcpc:    "LRCPC",    // Weaker release consistency (LDAPR, etc)
218	dcpop:    "DCPOP",    // Data cache clean to Point of Persistence (DC CVAP)
219	sha3:     "SHA3",     // SHA-3 instructions (EOR3, RAXI, XAR, BCAX)
220	sm3:      "SM3",      // SM3 instructions
221	sm4:      "SM4",      // SM4 instructions
222	asimddp:  "ASIMDDP",  // SIMD Dot Product
223	sha512:   "SHA512",   // SHA512 instructions
224	sve:      "SVE",      // Scalable Vector Extension
225	gpa:      "GPA",      // Generic Pointer Authentication
226}
227
228// CPUInfo contains information about the detected system CPU.
229type cpuInfo struct {
230	brandname      string   // Brand name reported by the CPU
231	vendorid       vendor   // Comparable CPU vendor ID
232	vendorstring   string   // Raw vendor string.
233	features       flags    // Features of the CPU (x64)
234	arm            armflags // Features of the CPU (arm)
235	physicalcores  int      // Number of physical processor cores in your CPU. Will be 0 if undetectable.
236	threadspercore int      // Number of threads per physical core. Will be 1 if undetectable.
237	logicalcores   int      // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
238	family         int      // CPU family number
239	model          int      // CPU model number
240	cacheline      int      // Cache line size in bytes. Will be 0 if undetectable.
241	hz             int64    // Clock speed, if known
242	cache          struct {
243		l1i int // L1 Instruction Cache (per core or shared). Will be -1 if undetected
244		l1d int // L1 Data Cache (per core or shared). Will be -1 if undetected
245		l2  int // L2 Cache (per core or shared). Will be -1 if undetected
246		l3  int // L3 Cache (per core, per ccx or shared). Will be -1 if undetected
247	}
248	sgx       sgxsupport
249	maxFunc   uint32
250	maxExFunc uint32
251}
252
253var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
254var cpuidex func(op, op2 uint32) (eax, ebx, ecx, edx uint32)
255var xgetbv func(index uint32) (eax, edx uint32)
256var rdtscpAsm func() (eax, ebx, ecx, edx uint32)
257
258// CPU contains information about the CPU as detected on startup,
259// or when Detect last was called.
260//
261// Use this as the primary entry point to you data.
262var cpu cpuInfo
263
264func init() {
265	initCPU()
266	detect()
267}
268
269// Detect will re-detect current CPU info.
270// This will replace the content of the exported CPU variable.
271//
272// Unless you expect the CPU to change while you are running your program
273// you should not need to call this function.
274// If you call this, you must ensure that no other goroutine is accessing the
275// exported CPU variable.
276func detect() {
277	// Set defaults
278	cpu.threadspercore = 1
279	cpu.cache.l1i = -1
280	cpu.cache.l1d = -1
281	cpu.cache.l2 = -1
282	cpu.cache.l3 = -1
283	addInfo(&cpu)
284}
285
286// Generated here: http://play.golang.org/p/BxFH2Gdc0G
287
288// Cmov indicates support of CMOV instructions
289func (c cpuInfo) cmov() bool {
290	return c.features&cmov != 0
291}
292
293// Amd3dnow indicates support of AMD 3DNOW! instructions
294func (c cpuInfo) amd3dnow() bool {
295	return c.features&amd3dnow != 0
296}
297
298// Amd3dnowExt indicates support of AMD 3DNOW! Extended instructions
299func (c cpuInfo) amd3dnowext() bool {
300	return c.features&amd3dnowext != 0
301}
302
303// VMX indicates support of VMX
304func (c cpuInfo) vmx() bool {
305	return c.features&vmx != 0
306}
307
308// MMX indicates support of MMX instructions
309func (c cpuInfo) mmx() bool {
310	return c.features&mmx != 0
311}
312
313// MMXExt indicates support of MMXEXT instructions
314// (SSE integer functions or AMD MMX ext)
315func (c cpuInfo) mmxext() bool {
316	return c.features&mmxext != 0
317}
318
319// SSE indicates support of SSE instructions
320func (c cpuInfo) sse() bool {
321	return c.features&sse != 0
322}
323
324// SSE2 indicates support of SSE 2 instructions
325func (c cpuInfo) sse2() bool {
326	return c.features&sse2 != 0
327}
328
329// SSE3 indicates support of SSE 3 instructions
330func (c cpuInfo) sse3() bool {
331	return c.features&sse3 != 0
332}
333
334// SSSE3 indicates support of SSSE 3 instructions
335func (c cpuInfo) ssse3() bool {
336	return c.features&ssse3 != 0
337}
338
339// SSE4 indicates support of SSE 4 (also called SSE 4.1) instructions
340func (c cpuInfo) sse4() bool {
341	return c.features&sse4 != 0
342}
343
344// SSE42 indicates support of SSE4.2 instructions
345func (c cpuInfo) sse42() bool {
346	return c.features&sse42 != 0
347}
348
349// AVX indicates support of AVX instructions
350// and operating system support of AVX instructions
351func (c cpuInfo) avx() bool {
352	return c.features&avx != 0
353}
354
355// AVX2 indicates support of AVX2 instructions
356func (c cpuInfo) avx2() bool {
357	return c.features&avx2 != 0
358}
359
360// FMA3 indicates support of FMA3 instructions
361func (c cpuInfo) fma3() bool {
362	return c.features&fma3 != 0
363}
364
365// FMA4 indicates support of FMA4 instructions
366func (c cpuInfo) fma4() bool {
367	return c.features&fma4 != 0
368}
369
370// XOP indicates support of XOP instructions
371func (c cpuInfo) xop() bool {
372	return c.features&xop != 0
373}
374
375// F16C indicates support of F16C instructions
376func (c cpuInfo) f16c() bool {
377	return c.features&f16c != 0
378}
379
380// BMI1 indicates support of BMI1 instructions
381func (c cpuInfo) bmi1() bool {
382	return c.features&bmi1 != 0
383}
384
385// BMI2 indicates support of BMI2 instructions
386func (c cpuInfo) bmi2() bool {
387	return c.features&bmi2 != 0
388}
389
390// TBM indicates support of TBM instructions
391// (AMD Trailing Bit Manipulation)
392func (c cpuInfo) tbm() bool {
393	return c.features&tbm != 0
394}
395
396// Lzcnt indicates support of LZCNT instruction
397func (c cpuInfo) lzcnt() bool {
398	return c.features&lzcnt != 0
399}
400
401// Popcnt indicates support of POPCNT instruction
402func (c cpuInfo) popcnt() bool {
403	return c.features&popcnt != 0
404}
405
406// HTT indicates the processor has Hyperthreading enabled
407func (c cpuInfo) htt() bool {
408	return c.features&htt != 0
409}
410
411// SSE2Slow indicates that SSE2 may be slow on this processor
412func (c cpuInfo) sse2slow() bool {
413	return c.features&sse2slow != 0
414}
415
416// SSE3Slow indicates that SSE3 may be slow on this processor
417func (c cpuInfo) sse3slow() bool {
418	return c.features&sse3slow != 0
419}
420
421// AesNi indicates support of AES-NI instructions
422// (Advanced Encryption Standard New Instructions)
423func (c cpuInfo) aesni() bool {
424	return c.features&aesni != 0
425}
426
427// Clmul indicates support of CLMUL instructions
428// (Carry-less Multiplication)
429func (c cpuInfo) clmul() bool {
430	return c.features&clmul != 0
431}
432
433// NX indicates support of NX (No-Execute) bit
434func (c cpuInfo) nx() bool {
435	return c.features&nx != 0
436}
437
438// SSE4A indicates support of AMD Barcelona microarchitecture SSE4a instructions
439func (c cpuInfo) sse4a() bool {
440	return c.features&sse4a != 0
441}
442
443// HLE indicates support of Hardware Lock Elision
444func (c cpuInfo) hle() bool {
445	return c.features&hle != 0
446}
447
448// RTM indicates support of Restricted Transactional Memory
449func (c cpuInfo) rtm() bool {
450	return c.features&rtm != 0
451}
452
453// Rdrand indicates support of RDRAND instruction is available
454func (c cpuInfo) rdrand() bool {
455	return c.features&rdrand != 0
456}
457
458// Rdseed indicates support of RDSEED instruction is available
459func (c cpuInfo) rdseed() bool {
460	return c.features&rdseed != 0
461}
462
463// ADX indicates support of Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
464func (c cpuInfo) adx() bool {
465	return c.features&adx != 0
466}
467
468// SHA indicates support of Intel SHA Extensions
469func (c cpuInfo) sha() bool {
470	return c.features&sha != 0
471}
472
473// AVX512F indicates support of AVX-512 Foundation
474func (c cpuInfo) avx512f() bool {
475	return c.features&avx512f != 0
476}
477
478// AVX512DQ indicates support of AVX-512 Doubleword and Quadword Instructions
479func (c cpuInfo) avx512dq() bool {
480	return c.features&avx512dq != 0
481}
482
483// AVX512IFMA indicates support of AVX-512 Integer Fused Multiply-Add Instructions
484func (c cpuInfo) avx512ifma() bool {
485	return c.features&avx512ifma != 0
486}
487
488// AVX512PF indicates support of AVX-512 Prefetch Instructions
489func (c cpuInfo) avx512pf() bool {
490	return c.features&avx512pf != 0
491}
492
493// AVX512ER indicates support of AVX-512 Exponential and Reciprocal Instructions
494func (c cpuInfo) avx512er() bool {
495	return c.features&avx512er != 0
496}
497
498// AVX512CD indicates support of AVX-512 Conflict Detection Instructions
499func (c cpuInfo) avx512cd() bool {
500	return c.features&avx512cd != 0
501}
502
503// AVX512BW indicates support of AVX-512 Byte and Word Instructions
504func (c cpuInfo) avx512bw() bool {
505	return c.features&avx512bw != 0
506}
507
508// AVX512VL indicates support of AVX-512 Vector Length Extensions
509func (c cpuInfo) avx512vl() bool {
510	return c.features&avx512vl != 0
511}
512
513// AVX512VBMI indicates support of AVX-512 Vector Bit Manipulation Instructions
514func (c cpuInfo) avx512vbmi() bool {
515	return c.features&avx512vbmi != 0
516}
517
518// AVX512VBMI2 indicates support of AVX-512 Vector Bit Manipulation Instructions, Version 2
519func (c cpuInfo) avx512vbmi2() bool {
520	return c.features&avx512vbmi2 != 0
521}
522
523// AVX512VNNI indicates support of AVX-512 Vector Neural Network Instructions
524func (c cpuInfo) avx512vnni() bool {
525	return c.features&avx512vnni != 0
526}
527
528// AVX512VPOPCNTDQ indicates support of AVX-512 Vector Population Count Doubleword and Quadword
529func (c cpuInfo) avx512vpopcntdq() bool {
530	return c.features&avx512vpopcntdq != 0
531}
532
533// GFNI indicates support of Galois Field New Instructions
534func (c cpuInfo) gfni() bool {
535	return c.features&gfni != 0
536}
537
538// VAES indicates support of Vector AES
539func (c cpuInfo) vaes() bool {
540	return c.features&vaes != 0
541}
542
543// AVX512BITALG indicates support of AVX-512 Bit Algorithms
544func (c cpuInfo) avx512bitalg() bool {
545	return c.features&avx512bitalg != 0
546}
547
548// VPCLMULQDQ indicates support of Carry-Less Multiplication Quadword
549func (c cpuInfo) vpclmulqdq() bool {
550	return c.features&vpclmulqdq != 0
551}
552
553// AVX512BF16 indicates support of
554func (c cpuInfo) avx512bf16() bool {
555	return c.features&avx512bf16 != 0
556}
557
558// AVX512VP2INTERSECT indicates support of
559func (c cpuInfo) avx512vp2intersect() bool {
560	return c.features&avx512vp2intersect != 0
561}
562
563// MPX indicates support of Intel MPX (Memory Protection Extensions)
564func (c cpuInfo) mpx() bool {
565	return c.features&mpx != 0
566}
567
568// ERMS indicates support of Enhanced REP MOVSB/STOSB
569func (c cpuInfo) erms() bool {
570	return c.features&erms != 0
571}
572
573// RDTSCP Instruction is available.
574func (c cpuInfo) rdtscp() bool {
575	return c.features&rdtscp != 0
576}
577
578// CX16 indicates if CMPXCHG16B instruction is available.
579func (c cpuInfo) cx16() bool {
580	return c.features&cx16 != 0
581}
582
583// TSX is split into HLE (Hardware Lock Elision) and RTM (Restricted Transactional Memory) detection.
584// So TSX simply checks that.
585func (c cpuInfo) tsx() bool {
586	return c.features&(hle|rtm) == hle|rtm
587}
588
589// Atom indicates an Atom processor
590func (c cpuInfo) atom() bool {
591	return c.features&atom != 0
592}
593
594// Intel returns true if vendor is recognized as Intel
595func (c cpuInfo) intel() bool {
596	return c.vendorid == intel
597}
598
599// AMD returns true if vendor is recognized as AMD
600func (c cpuInfo) amd() bool {
601	return c.vendorid == amd
602}
603
604// Hygon returns true if vendor is recognized as Hygon
605func (c cpuInfo) hygon() bool {
606	return c.vendorid == hygon
607}
608
609// Transmeta returns true if vendor is recognized as Transmeta
610func (c cpuInfo) transmeta() bool {
611	return c.vendorid == transmeta
612}
613
614// NSC returns true if vendor is recognized as National Semiconductor
615func (c cpuInfo) nsc() bool {
616	return c.vendorid == nsc
617}
618
619// VIA returns true if vendor is recognized as VIA
620func (c cpuInfo) via() bool {
621	return c.vendorid == via
622}
623
624// RTCounter returns the 64-bit time-stamp counter
625// Uses the RDTSCP instruction. The value 0 is returned
626// if the CPU does not support the instruction.
627func (c cpuInfo) rtcounter() uint64 {
628	if !c.rdtscp() {
629		return 0
630	}
631	a, _, _, d := rdtscpAsm()
632	return uint64(a) | (uint64(d) << 32)
633}
634
635// Ia32TscAux returns the IA32_TSC_AUX part of the RDTSCP.
636// This variable is OS dependent, but on Linux contains information
637// about the current cpu/core the code is running on.
638// If the RDTSCP instruction isn't supported on the CPU, the value 0 is returned.
639func (c cpuInfo) ia32tscaux() uint32 {
640	if !c.rdtscp() {
641		return 0
642	}
643	_, _, ecx, _ := rdtscpAsm()
644	return ecx
645}
646
647// LogicalCPU will return the Logical CPU the code is currently executing on.
648// This is likely to change when the OS re-schedules the running thread
649// to another CPU.
650// If the current core cannot be detected, -1 will be returned.
651func (c cpuInfo) logicalcpu() int {
652	if c.maxFunc < 1 {
653		return -1
654	}
655	_, ebx, _, _ := cpuid(1)
656	return int(ebx >> 24)
657}
658
659// hertz tries to compute the clock speed of the CPU. If leaf 15 is
660// supported, use it, otherwise parse the brand string. Yes, really.
661func hertz(model string) int64 {
662	mfi := maxFunctionID()
663	if mfi >= 0x15 {
664		eax, ebx, ecx, _ := cpuid(0x15)
665		if eax != 0 && ebx != 0 && ecx != 0 {
666			return int64((int64(ecx) * int64(ebx)) / int64(eax))
667		}
668	}
669	// computeHz determines the official rated speed of a CPU from its brand
670	// string. This insanity is *actually the official documented way to do
671	// this according to Intel*, prior to leaf 0x15 existing. The official
672	// documentation only shows this working for exactly `x.xx` or `xxxx`
673	// cases, e.g., `2.50GHz` or `1300MHz`; this parser will accept other
674	// sizes.
675	hz := strings.LastIndex(model, "Hz")
676	if hz < 3 {
677		return -1
678	}
679	var multiplier int64
680	switch model[hz-1] {
681	case 'M':
682		multiplier = 1000 * 1000
683	case 'G':
684		multiplier = 1000 * 1000 * 1000
685	case 'T':
686		multiplier = 1000 * 1000 * 1000 * 1000
687	}
688	if multiplier == 0 {
689		return -1
690	}
691	freq := int64(0)
692	divisor := int64(0)
693	decimalShift := int64(1)
694	var i int
695	for i = hz - 2; i >= 0 && model[i] != ' '; i-- {
696		if model[i] >= '0' && model[i] <= '9' {
697			freq += int64(model[i]-'0') * decimalShift
698			decimalShift *= 10
699		} else if model[i] == '.' {
700			if divisor != 0 {
701				return -1
702			}
703			divisor = decimalShift
704		} else {
705			return -1
706		}
707	}
708	// we didn't find a space
709	if i < 0 {
710		return -1
711	}
712	if divisor != 0 {
713		return (freq * multiplier) / divisor
714	}
715	return freq * multiplier
716}
717
718// VM Will return true if the cpu id indicates we are in
719// a virtual machine. This is only a hint, and will very likely
720// have many false negatives.
721func (c cpuInfo) vm() bool {
722	switch c.vendorid {
723	case msvm, kvm, vmware, xenhvm, bhyve:
724		return true
725	}
726	return false
727}
728
729// Flags contains detected cpu features and characteristics
730type flags uint64
731
732// ArmFlags contains detected ARM cpu features and characteristics
733type armflags uint64
734
735// String returns a string representation of the detected
736// CPU features.
737func (f flags) String() string {
738	return strings.Join(f.strings(), ",")
739}
740
741// Strings returns an array of the detected features.
742func (f flags) strings() []string {
743	r := make([]string, 0, 20)
744	for i := uint(0); i < 64; i++ {
745		key := flags(1 << i)
746		val := flagNames[key]
747		if f&key != 0 {
748			r = append(r, val)
749		}
750	}
751	return r
752}
753
754// String returns a string representation of the detected
755// CPU features.
756func (f armflags) String() string {
757	return strings.Join(f.strings(), ",")
758}
759
760// Strings returns an array of the detected features.
761func (f armflags) strings() []string {
762	r := make([]string, 0, 20)
763	for i := uint(0); i < 64; i++ {
764		key := armflags(1 << i)
765		val := flagNamesArm[key]
766		if f&key != 0 {
767			r = append(r, val)
768		}
769	}
770	return r
771}
772func maxExtendedFunction() uint32 {
773	eax, _, _, _ := cpuid(0x80000000)
774	return eax
775}
776
777func maxFunctionID() uint32 {
778	a, _, _, _ := cpuid(0)
779	return a
780}
781
782func brandName() string {
783	if maxExtendedFunction() >= 0x80000004 {
784		v := make([]uint32, 0, 48)
785		for i := uint32(0); i < 3; i++ {
786			a, b, c, d := cpuid(0x80000002 + i)
787			v = append(v, a, b, c, d)
788		}
789		return strings.Trim(string(valAsString(v...)), " ")
790	}
791	return "unknown"
792}
793
794func threadsPerCore() int {
795	mfi := maxFunctionID()
796	vend, _ := vendorID()
797
798	if mfi < 0x4 || (vend != intel && vend != amd) {
799		return 1
800	}
801
802	if mfi < 0xb {
803		if vend != intel {
804			return 1
805		}
806		_, b, _, d := cpuid(1)
807		if (d & (1 << 28)) != 0 {
808			// v will contain logical core count
809			v := (b >> 16) & 255
810			if v > 1 {
811				a4, _, _, _ := cpuid(4)
812				// physical cores
813				v2 := (a4 >> 26) + 1
814				if v2 > 0 {
815					return int(v) / int(v2)
816				}
817			}
818		}
819		return 1
820	}
821	_, b, _, _ := cpuidex(0xb, 0)
822	if b&0xffff == 0 {
823		return 1
824	}
825	return int(b & 0xffff)
826}
827
828func logicalCores() int {
829	mfi := maxFunctionID()
830	v, _ := vendorID()
831	switch v {
832	case intel:
833		// Use this on old Intel processors
834		if mfi < 0xb {
835			if mfi < 1 {
836				return 0
837			}
838			// CPUID.1:EBX[23:16] represents the maximum number of addressable IDs (initial APIC ID)
839			// that can be assigned to logical processors in a physical package.
840			// The value may not be the same as the number of logical processors that are present in the hardware of a physical package.
841			_, ebx, _, _ := cpuid(1)
842			logical := (ebx >> 16) & 0xff
843			return int(logical)
844		}
845		_, b, _, _ := cpuidex(0xb, 1)
846		return int(b & 0xffff)
847	case amd, hygon:
848		_, b, _, _ := cpuid(1)
849		return int((b >> 16) & 0xff)
850	default:
851		return 0
852	}
853}
854
855func familyModel() (int, int) {
856	if maxFunctionID() < 0x1 {
857		return 0, 0
858	}
859	eax, _, _, _ := cpuid(1)
860	family := ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff)
861	model := ((eax >> 4) & 0xf) + ((eax >> 12) & 0xf0)
862	return int(family), int(model)
863}
864
865func physicalCores() int {
866	v, _ := vendorID()
867	switch v {
868	case intel:
869		return logicalCores() / threadsPerCore()
870	case amd, hygon:
871		lc := logicalCores()
872		tpc := threadsPerCore()
873		if lc > 0 && tpc > 0 {
874			return lc / tpc
875		}
876		// The following is inaccurate on AMD EPYC 7742 64-Core Processor
877
878		if maxExtendedFunction() >= 0x80000008 {
879			_, _, c, _ := cpuid(0x80000008)
880			return int(c&0xff) + 1
881		}
882	}
883	return 0
884}
885
886// Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID
887var vendorMapping = map[string]vendor{
888	"AMDisbetter!": amd,
889	"AuthenticAMD": amd,
890	"CentaurHauls": via,
891	"GenuineIntel": intel,
892	"TransmetaCPU": transmeta,
893	"GenuineTMx86": transmeta,
894	"Geode by NSC": nsc,
895	"VIA VIA VIA ": via,
896	"KVMKVMKVMKVM": kvm,
897	"Microsoft Hv": msvm,
898	"VMwareVMware": vmware,
899	"XenVMMXenVMM": xenhvm,
900	"bhyve bhyve ": bhyve,
901	"HygonGenuine": hygon,
902	"Vortex86 SoC": sis,
903	"SiS SiS SiS ": sis,
904	"RiseRiseRise": sis,
905	"Genuine  RDC": rdc,
906}
907
908func vendorID() (vendor, string) {
909	_, b, c, d := cpuid(0)
910	v := string(valAsString(b, d, c))
911	vend, ok := vendorMapping[v]
912	if !ok {
913		return other, v
914	}
915	return vend, v
916}
917
918func cacheLine() int {
919	if maxFunctionID() < 0x1 {
920		return 0
921	}
922
923	_, ebx, _, _ := cpuid(1)
924	cache := (ebx & 0xff00) >> 5 // cflush size
925	if cache == 0 && maxExtendedFunction() >= 0x80000006 {
926		_, _, ecx, _ := cpuid(0x80000006)
927		cache = ecx & 0xff // cacheline size
928	}
929	// TODO: Read from Cache and TLB Information
930	return int(cache)
931}
932
933func (c *cpuInfo) cacheSize() {
934	c.cache.l1d = -1
935	c.cache.l1i = -1
936	c.cache.l2 = -1
937	c.cache.l3 = -1
938	vendor, _ := vendorID()
939	switch vendor {
940	case intel:
941		if maxFunctionID() < 4 {
942			return
943		}
944		for i := uint32(0); ; i++ {
945			eax, ebx, ecx, _ := cpuidex(4, i)
946			cacheType := eax & 15
947			if cacheType == 0 {
948				break
949			}
950			cacheLevel := (eax >> 5) & 7
951			coherency := int(ebx&0xfff) + 1
952			partitions := int((ebx>>12)&0x3ff) + 1
953			associativity := int((ebx>>22)&0x3ff) + 1
954			sets := int(ecx) + 1
955			size := associativity * partitions * coherency * sets
956			switch cacheLevel {
957			case 1:
958				if cacheType == 1 {
959					// 1 = Data Cache
960					c.cache.l1d = size
961				} else if cacheType == 2 {
962					// 2 = Instruction Cache
963					c.cache.l1i = size
964				} else {
965					if c.cache.l1d < 0 {
966						c.cache.l1i = size
967					}
968					if c.cache.l1i < 0 {
969						c.cache.l1i = size
970					}
971				}
972			case 2:
973				c.cache.l2 = size
974			case 3:
975				c.cache.l3 = size
976			}
977		}
978	case amd, hygon:
979		// Untested.
980		if maxExtendedFunction() < 0x80000005 {
981			return
982		}
983		_, _, ecx, edx := cpuid(0x80000005)
984		c.cache.l1d = int(((ecx >> 24) & 0xFF) * 1024)
985		c.cache.l1i = int(((edx >> 24) & 0xFF) * 1024)
986
987		if maxExtendedFunction() < 0x80000006 {
988			return
989		}
990		_, _, ecx, _ = cpuid(0x80000006)
991		c.cache.l2 = int(((ecx >> 16) & 0xFFFF) * 1024)
992
993		// CPUID Fn8000_001D_EAX_x[N:0] Cache Properties
994		if maxExtendedFunction() < 0x8000001D {
995			return
996		}
997		for i := uint32(0); i < math.MaxUint32; i++ {
998			eax, ebx, ecx, _ := cpuidex(0x8000001D, i)
999
1000			level := (eax >> 5) & 7
1001			cacheNumSets := ecx + 1
1002			cacheLineSize := 1 + (ebx & 2047)
1003			cachePhysPartitions := 1 + ((ebx >> 12) & 511)
1004			cacheNumWays := 1 + ((ebx >> 22) & 511)
1005
1006			typ := eax & 15
1007			size := int(cacheNumSets * cacheLineSize * cachePhysPartitions * cacheNumWays)
1008			if typ == 0 {
1009				return
1010			}
1011
1012			switch level {
1013			case 1:
1014				switch typ {
1015				case 1:
1016					// Data cache
1017					c.cache.l1d = size
1018				case 2:
1019					// Inst cache
1020					c.cache.l1i = size
1021				default:
1022					if c.cache.l1d < 0 {
1023						c.cache.l1i = size
1024					}
1025					if c.cache.l1i < 0 {
1026						c.cache.l1i = size
1027					}
1028				}
1029			case 2:
1030				c.cache.l2 = size
1031			case 3:
1032				c.cache.l3 = size
1033			}
1034		}
1035	}
1036
1037	return
1038}
1039
1040type sgxepcsection struct {
1041	baseaddress uint64
1042	epcsize     uint64
1043}
1044
1045type sgxsupport struct {
1046	available           bool
1047	launchcontrol       bool
1048	sgx1supported       bool
1049	sgx2supported       bool
1050	maxenclavesizenot64 int64
1051	maxenclavesize64    int64
1052	epcsections         []sgxepcsection
1053}
1054
1055func hasSGX(available, lc bool) (rval sgxsupport) {
1056	rval.available = available
1057
1058	if !available {
1059		return
1060	}
1061
1062	rval.launchcontrol = lc
1063
1064	a, _, _, d := cpuidex(0x12, 0)
1065	rval.sgx1supported = a&0x01 != 0
1066	rval.sgx2supported = a&0x02 != 0
1067	rval.maxenclavesizenot64 = 1 << (d & 0xFF)     // pow 2
1068	rval.maxenclavesize64 = 1 << ((d >> 8) & 0xFF) // pow 2
1069	rval.epcsections = make([]sgxepcsection, 0)
1070
1071	for subleaf := uint32(2); subleaf < 2+8; subleaf++ {
1072		eax, ebx, ecx, edx := cpuidex(0x12, subleaf)
1073		leafType := eax & 0xf
1074
1075		if leafType == 0 {
1076			// Invalid subleaf, stop iterating
1077			break
1078		} else if leafType == 1 {
1079			// EPC Section subleaf
1080			baseAddress := uint64(eax&0xfffff000) + (uint64(ebx&0x000fffff) << 32)
1081			size := uint64(ecx&0xfffff000) + (uint64(edx&0x000fffff) << 32)
1082
1083			section := sgxepcsection{baseaddress: baseAddress, epcsize: size}
1084			rval.epcsections = append(rval.epcsections, section)
1085		}
1086	}
1087
1088	return
1089}
1090
1091func support() flags {
1092	mfi := maxFunctionID()
1093	vend, _ := vendorID()
1094	if mfi < 0x1 {
1095		return 0
1096	}
1097	rval := uint64(0)
1098	_, _, c, d := cpuid(1)
1099	if (d & (1 << 15)) != 0 {
1100		rval |= cmov
1101	}
1102	if (d & (1 << 23)) != 0 {
1103		rval |= mmx
1104	}
1105	if (d & (1 << 25)) != 0 {
1106		rval |= mmxext
1107	}
1108	if (d & (1 << 25)) != 0 {
1109		rval |= sse
1110	}
1111	if (d & (1 << 26)) != 0 {
1112		rval |= sse2
1113	}
1114	if (c & 1) != 0 {
1115		rval |= sse3
1116	}
1117	if (c & (1 << 5)) != 0 {
1118		rval |= vmx
1119	}
1120	if (c & 0x00000200) != 0 {
1121		rval |= ssse3
1122	}
1123	if (c & 0x00080000) != 0 {
1124		rval |= sse4
1125	}
1126	if (c & 0x00100000) != 0 {
1127		rval |= sse42
1128	}
1129	if (c & (1 << 25)) != 0 {
1130		rval |= aesni
1131	}
1132	if (c & (1 << 1)) != 0 {
1133		rval |= clmul
1134	}
1135	if c&(1<<23) != 0 {
1136		rval |= popcnt
1137	}
1138	if c&(1<<30) != 0 {
1139		rval |= rdrand
1140	}
1141	if c&(1<<29) != 0 {
1142		rval |= f16c
1143	}
1144	if c&(1<<13) != 0 {
1145		rval |= cx16
1146	}
1147	if vend == intel && (d&(1<<28)) != 0 && mfi >= 4 {
1148		if threadsPerCore() > 1 {
1149			rval |= htt
1150		}
1151	}
1152	if vend == amd && (d&(1<<28)) != 0 && mfi >= 4 {
1153		if threadsPerCore() > 1 {
1154			rval |= htt
1155		}
1156	}
1157	// Check XGETBV, OXSAVE and AVX bits
1158	if c&(1<<26) != 0 && c&(1<<27) != 0 && c&(1<<28) != 0 {
1159		// Check for OS support
1160		eax, _ := xgetbv(0)
1161		if (eax & 0x6) == 0x6 {
1162			rval |= avx
1163			if (c & 0x00001000) != 0 {
1164				rval |= fma3
1165			}
1166		}
1167	}
1168
1169	// Check AVX2, AVX2 requires OS support, but BMI1/2 don't.
1170	if mfi >= 7 {
1171		_, ebx, ecx, edx := cpuidex(7, 0)
1172		eax1, _, _, _ := cpuidex(7, 1)
1173		if (rval&avx) != 0 && (ebx&0x00000020) != 0 {
1174			rval |= avx2
1175		}
1176		if (ebx & 0x00000008) != 0 {
1177			rval |= bmi1
1178			if (ebx & 0x00000100) != 0 {
1179				rval |= bmi2
1180			}
1181		}
1182		if ebx&(1<<2) != 0 {
1183			rval |= sgx
1184		}
1185		if ebx&(1<<4) != 0 {
1186			rval |= hle
1187		}
1188		if ebx&(1<<9) != 0 {
1189			rval |= erms
1190		}
1191		if ebx&(1<<11) != 0 {
1192			rval |= rtm
1193		}
1194		if ebx&(1<<14) != 0 {
1195			rval |= mpx
1196		}
1197		if ebx&(1<<18) != 0 {
1198			rval |= rdseed
1199		}
1200		if ebx&(1<<19) != 0 {
1201			rval |= adx
1202		}
1203		if ebx&(1<<29) != 0 {
1204			rval |= sha
1205		}
1206		if edx&(1<<26) != 0 {
1207			rval |= ibpb
1208		}
1209		if ecx&(1<<30) != 0 {
1210			rval |= sgxlc
1211		}
1212		if edx&(1<<27) != 0 {
1213			rval |= stibp
1214		}
1215
1216		// Only detect AVX-512 features if XGETBV is supported
1217		if c&((1<<26)|(1<<27)) == (1<<26)|(1<<27) {
1218			// Check for OS support
1219			eax, _ := xgetbv(0)
1220
1221			// Verify that XCR0[7:5] = ‘111b’ (OPMASK state, upper 256-bit of ZMM0-ZMM15 and
1222			// ZMM16-ZMM31 state are enabled by OS)
1223			/// and that XCR0[2:1] = ‘11b’ (XMM state and YMM state are enabled by OS).
1224			if (eax>>5)&7 == 7 && (eax>>1)&3 == 3 {
1225				if ebx&(1<<16) != 0 {
1226					rval |= avx512f
1227				}
1228				if ebx&(1<<17) != 0 {
1229					rval |= avx512dq
1230				}
1231				if ebx&(1<<21) != 0 {
1232					rval |= avx512ifma
1233				}
1234				if ebx&(1<<26) != 0 {
1235					rval |= avx512pf
1236				}
1237				if ebx&(1<<27) != 0 {
1238					rval |= avx512er
1239				}
1240				if ebx&(1<<28) != 0 {
1241					rval |= avx512cd
1242				}
1243				if ebx&(1<<30) != 0 {
1244					rval |= avx512bw
1245				}
1246				if ebx&(1<<31) != 0 {
1247					rval |= avx512vl
1248				}
1249				// ecx
1250				if ecx&(1<<1) != 0 {
1251					rval |= avx512vbmi
1252				}
1253				if ecx&(1<<6) != 0 {
1254					rval |= avx512vbmi2
1255				}
1256				if ecx&(1<<8) != 0 {
1257					rval |= gfni
1258				}
1259				if ecx&(1<<9) != 0 {
1260					rval |= vaes
1261				}
1262				if ecx&(1<<10) != 0 {
1263					rval |= vpclmulqdq
1264				}
1265				if ecx&(1<<11) != 0 {
1266					rval |= avx512vnni
1267				}
1268				if ecx&(1<<12) != 0 {
1269					rval |= avx512bitalg
1270				}
1271				if ecx&(1<<14) != 0 {
1272					rval |= avx512vpopcntdq
1273				}
1274				// edx
1275				if edx&(1<<8) != 0 {
1276					rval |= avx512vp2intersect
1277				}
1278				// cpuid eax 07h,ecx=1
1279				if eax1&(1<<5) != 0 {
1280					rval |= avx512bf16
1281				}
1282			}
1283		}
1284	}
1285
1286	if maxExtendedFunction() >= 0x80000001 {
1287		_, _, c, d := cpuid(0x80000001)
1288		if (c & (1 << 5)) != 0 {
1289			rval |= lzcnt
1290			rval |= popcnt
1291		}
1292		if (d & (1 << 31)) != 0 {
1293			rval |= amd3dnow
1294		}
1295		if (d & (1 << 30)) != 0 {
1296			rval |= amd3dnowext
1297		}
1298		if (d & (1 << 23)) != 0 {
1299			rval |= mmx
1300		}
1301		if (d & (1 << 22)) != 0 {
1302			rval |= mmxext
1303		}
1304		if (c & (1 << 6)) != 0 {
1305			rval |= sse4a
1306		}
1307		if d&(1<<20) != 0 {
1308			rval |= nx
1309		}
1310		if d&(1<<27) != 0 {
1311			rval |= rdtscp
1312		}
1313
1314		/* Allow for selectively disabling SSE2 functions on AMD processors
1315		   with SSE2 support but not SSE4a. This includes Athlon64, some
1316		   Opteron, and some Sempron processors. MMX, SSE, or 3DNow! are faster
1317		   than SSE2 often enough to utilize this special-case flag.
1318		   AV_CPU_FLAG_SSE2 and AV_CPU_FLAG_SSE2SLOW are both set in this case
1319		   so that SSE2 is used unless explicitly disabled by checking
1320		   AV_CPU_FLAG_SSE2SLOW. */
1321		if vend != intel &&
1322			rval&sse2 != 0 && (c&0x00000040) == 0 {
1323			rval |= sse2slow
1324		}
1325
1326		/* XOP and FMA4 use the AVX instruction coding scheme, so they can't be
1327		 * used unless the OS has AVX support. */
1328		if (rval & avx) != 0 {
1329			if (c & 0x00000800) != 0 {
1330				rval |= xop
1331			}
1332			if (c & 0x00010000) != 0 {
1333				rval |= fma4
1334			}
1335		}
1336
1337		if vend == intel {
1338			family, model := familyModel()
1339			if family == 6 && (model == 9 || model == 13 || model == 14) {
1340				/* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and
1341				 * 6/14 (core1 "yonah") theoretically support sse2, but it's
1342				 * usually slower than mmx. */
1343				if (rval & sse2) != 0 {
1344					rval |= sse2slow
1345				}
1346				if (rval & sse3) != 0 {
1347					rval |= sse3slow
1348				}
1349			}
1350			/* The Atom processor has SSSE3 support, which is useful in many cases,
1351			 * but sometimes the SSSE3 version is slower than the SSE2 equivalent
1352			 * on the Atom, but is generally faster on other processors supporting
1353			 * SSSE3. This flag allows for selectively disabling certain SSSE3
1354			 * functions on the Atom. */
1355			if family == 6 && model == 28 {
1356				rval |= atom
1357			}
1358		}
1359	}
1360	return flags(rval)
1361}
1362
1363func valAsString(values ...uint32) []byte {
1364	r := make([]byte, 4*len(values))
1365	for i, v := range values {
1366		dst := r[i*4:]
1367		dst[0] = byte(v & 0xff)
1368		dst[1] = byte((v >> 8) & 0xff)
1369		dst[2] = byte((v >> 16) & 0xff)
1370		dst[3] = byte((v >> 24) & 0xff)
1371		switch {
1372		case dst[0] == 0:
1373			return r[:i*4]
1374		case dst[1] == 0:
1375			return r[:i*4+1]
1376		case dst[2] == 0:
1377			return r[:i*4+2]
1378		case dst[3] == 0:
1379			return r[:i*4+3]
1380		}
1381	}
1382	return r
1383}
1384
1385// Single-precision and double-precision floating point
1386func (c cpuInfo) armfp() bool {
1387	return c.arm&fp != 0
1388}
1389
1390// Advanced SIMD
1391func (c cpuInfo) armasimd() bool {
1392	return c.arm&asimd != 0
1393}
1394
1395// Generic timer
1396func (c cpuInfo) armevtstrm() bool {
1397	return c.arm&evtstrm != 0
1398}
1399
1400// AES instructions
1401func (c cpuInfo) armaes() bool {
1402	return c.arm&aes != 0
1403}
1404
1405// Polynomial Multiply instructions (PMULL/PMULL2)
1406func (c cpuInfo) armpmull() bool {
1407	return c.arm&pmull != 0
1408}
1409
1410// SHA-1 instructions (SHA1C, etc)
1411func (c cpuInfo) armsha1() bool {
1412	return c.arm&sha1 != 0
1413}
1414
1415// SHA-2 instructions (SHA256H, etc)
1416func (c cpuInfo) armsha2() bool {
1417	return c.arm&sha2 != 0
1418}
1419
1420// CRC32/CRC32C instructions
1421func (c cpuInfo) armcrc32() bool {
1422	return c.arm&crc32 != 0
1423}
1424
1425// Large System Extensions (LSE)
1426func (c cpuInfo) armatomics() bool {
1427	return c.arm&atomics != 0
1428}
1429
1430// Half-precision floating point
1431func (c cpuInfo) armfphp() bool {
1432	return c.arm&fphp != 0
1433}
1434
1435// Advanced SIMD half-precision floating point
1436func (c cpuInfo) armasimdhp() bool {
1437	return c.arm&asimdhp != 0
1438}
1439
1440// Rounding Double Multiply Accumulate/Subtract (SQRDMLAH/SQRDMLSH)
1441func (c cpuInfo) armasimdrdm() bool {
1442	return c.arm&asimdrdm != 0
1443}
1444
1445// Javascript-style double->int convert (FJCVTZS)
1446func (c cpuInfo) armjscvt() bool {
1447	return c.arm&jscvt != 0
1448}
1449
1450// Floatin point complex number addition and multiplication
1451func (c cpuInfo) armfcma() bool {
1452	return c.arm&fcma != 0
1453}
1454
1455// Weaker release consistency (LDAPR, etc)
1456func (c cpuInfo) armlrcpc() bool {
1457	return c.arm&lrcpc != 0
1458}
1459
1460// Data cache clean to Point of Persistence (DC CVAP)
1461func (c cpuInfo) armdcpop() bool {
1462	return c.arm&dcpop != 0
1463}
1464
1465// SHA-3 instructions (EOR3, RAXI, XAR, BCAX)
1466func (c cpuInfo) armsha3() bool {
1467	return c.arm&sha3 != 0
1468}
1469
1470// SM3 instructions
1471func (c cpuInfo) armsm3() bool {
1472	return c.arm&sm3 != 0
1473}
1474
1475// SM4 instructions
1476func (c cpuInfo) armsm4() bool {
1477	return c.arm&sm4 != 0
1478}
1479
1480// SIMD Dot Product
1481func (c cpuInfo) armasimddp() bool {
1482	return c.arm&asimddp != 0
1483}
1484
1485// SHA512 instructions
1486func (c cpuInfo) armsha512() bool {
1487	return c.arm&sha512 != 0
1488}
1489
1490// Scalable Vector Extension
1491func (c cpuInfo) armsve() bool {
1492	return c.arm&sve != 0
1493}
1494
1495// Generic Pointer Authentication
1496func (c cpuInfo) armgpa() bool {
1497	return c.arm&gpa != 0
1498}
1499