// File: /workspace/github_c_makefile_star2_O3/enzo1982[P]smooth/classes/system/cpu.cpp
// Function: smooth::System::CPU::GetCPUID() const
S::Errors::Error S::System::CPU::GetCPUID() const
{
	static Bool	 initialized = False;
	static Bool	 failed	     = False;

	/* Return if we are already initialized or failed before.
	 */
	if (initialized) return Success();
	if (failed)	 return Error();

	/* Find total number of CPUs if CPUID is not available.
	 */
	if (!cpuid_present())
	{
		/* Set to initialized and get number of CPUs.
		 */
		initialized    = True;

		numCores       = cpuid_get_total_cpus();
		numLogicalCPUs = numCores;

#if defined __APPLE__ && defined __aarch64__
		/* Apple uses an HMP architecture with power efficient cores
		 * showing performance characteristics similar to threads in
		 * an SMT system. We assume there are 4 power efficient cores
		 * and treat them the same way as SMT threads.
		 */
		if (numCores >= 6) numCores -= 4;
#endif

		return Success();
	}

	/* Get actual CPUID data.
	 */
	cpu_raw_data_array_t	 raw;
	system_id_t		 system;

	failed	       = True;

	if (cpuid_get_all_raw_data(&raw)    < 0) return Error();
	if (cpu_identify_all(&raw, &system) < 0) return Error();

	/* OK, set to initialized.
	 */
	initialized    = True;
	failed	       = False;

	/* Set vendor and brand strings.
	 */
	cpu_id_t& data = system.cpu_types[0];

	vendorString   = data.vendor_str;
	brandString    = data.brand_str;

	if (brandString == NIL) brandString = data.cpu_codename;

	/* Find number of cores and logical CPUs per processor.
	 */
	numCores       = 0;
	numLogicalCPUs = 0;

	for (Int i = 0; i < system.num_cpu_types; i++)
	{
		numCores       += system.cpu_types[i].num_cores;
		numLogicalCPUs += system.cpu_types[i].num_logical_cpus;
	}

	/* Find number of processors and mutiply core numbers.
	 */
	Int	 numTotalCPUs  = cpuid_get_total_cpus();
	Int	 numProcessors = numTotalCPUs / numLogicalCPUs;

	numCores       *= numProcessors;
	numLogicalCPUs *= numProcessors;

	/* Set feature flags.
	 */
	hasMMX	       = data.flags[CPU_FEATURE_MMX];
	hasMMXExt      = data.flags[CPU_FEATURE_MMXEXT];

	hasSSE	       = data.flags[CPU_FEATURE_SSE];
	hasSSE2	       = data.flags[CPU_FEATURE_SSE2];
	hasSSE3	       = data.flags[CPU_FEATURE_PNI];
	hasSSSE3       = data.flags[CPU_FEATURE_SSSE3];
	hasSSE4_1      = data.flags[CPU_FEATURE_SSE4_1];
	hasSSE4_2      = data.flags[CPU_FEATURE_SSE4_2];
	hasSSE4a       = data.flags[CPU_FEATURE_SSE4A];

	hasAVX	       = data.flags[CPU_FEATURE_AVX];
	hasAVX2	       = data.flags[CPU_FEATURE_AVX2];

	has3DNow       = data.flags[CPU_FEATURE_3DNOW];
	has3DNowExt    = data.flags[CPU_FEATURE_3DNOWEXT];

	hasHT	       = data.flags[CPU_FEATURE_HT];
	hasNX	       = data.flags[CPU_FEATURE_NX];

	hasVMX	       = data.flags[CPU_FEATURE_VMX];
	hasSVM	       = data.flags[CPU_FEATURE_SVM];

	/* Free CPUID data.
	 */
	cpuid_free_system_id(&system);
	cpuid_free_raw_data_array(&raw);

	return Success();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x40, %rsp
movq %rdi, %rbx
cmpb $0x1, 0xc66b7(%rip)     # 0x175ef9
jne 0xaf85e
movq 0xbbe7d(%rip), %rax     # 0x16b6c8
addq $0x10, %rax
movq %rax, (%rbx)
movl $0x0, 0x8(%rbx)
jmp 0xaface
cmpb $0x1, 0xc6695(%rip)     # 0x175efa
jne 0xaf881
movq 0xbbe5a(%rip), %rax     # 0x16b6c8
addq $0x10, %rax
movq %rax, (%rbx)
movl $0xffffffff, 0x8(%rbx)  # imm = 0xFFFFFFFF
jmp 0xaface
callq 0xc7284
testl %eax, %eax
je 0xafade
movb $0x1, 0xc6665(%rip)     # 0x175efa
leaq 0x8(%rsp), %rdi
callq 0xc746b
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
testl %eax, %eax
js 0xafabd
leaq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0xc89fe
testl %eax, %eax
js 0xafabd
movb $0x1, 0xc662f(%rip)     # 0x175ef9
movb $0x0, 0xc6629(%rip)     # 0x175efa
movq 0x20(%rsp), %r15
leaq 0x4(%r15), %rsi
movq 0xbbdbf(%rip), %rdi     # 0x16b6a0
callq 0x55f40
leaq 0x14(%r15), %rsi
movq 0xbbeff(%rip), %r14     # 0x16b7f0
movq %r14, %rdi
callq 0x55f40
xorl %ebp, %ebp
movq %r14, %rdi
xorl %esi, %esi
callq 0x55260
testb %al, %al
je 0xaf91c
leaq 0x150(%r15), %rsi
movq 0xbbed9(%rip), %rdi     # 0x16b7f0
callq 0x55f40
movq 0xbbc0d(%rip), %r12     # 0x16b530
movl %ebp, (%r12)
movq 0xbbe3a(%rip), %r14     # 0x16b768
movl %ebp, (%r14)
movzbl 0x18(%rsp), %ecx
testq %rcx, %rcx
je 0xaf96e
movq 0x20(%rsp), %rax
imulq $0x21e0, %rcx, %rcx     # imm = 0x21E0
xorl %edx, %edx
xorl %esi, %esi
xorl %edi, %edi
addl 0xec(%rax,%rdx), %esi
movl %esi, (%r12)
addl 0xf0(%rax,%rdx), %edi
movl %edi, (%r14)
addq $0x21e0, %rdx           # imm = 0x21E0
cmpq %rdx, %rcx
jne 0xaf94d
callq 0xc727a
movl (%r14), %ecx
cltd
idivl %ecx
movl (%r12), %edx
imull %eax, %edx
movl %edx, (%r12)
imull %ecx, %eax
movl %eax, (%r14)
cmpb $0x0, 0x6d(%r15)
movq 0xbbb12(%rip), %rax     # 0x16b4a8
setne (%rax)
cmpb $0x0, 0x8f(%r15)
movq 0xbc510(%rip), %rax     # 0x16beb8
setne (%rax)
cmpb $0x0, 0x6f(%r15)
movq 0xbba21(%rip), %rax     # 0x16b3d8
setne (%rax)
cmpb $0x0, 0x70(%r15)
movq 0xbbeea(%rip), %rax     # 0x16b8b0
setne (%rax)
cmpb $0x0, 0x76(%r15)
movq 0xbc2c3(%rip), %rax     # 0x16bc98
setne (%rax)
cmpb $0x0, 0x7f(%r15)
movq 0xbbb6c(%rip), %rax     # 0x16b550
setne (%rax)
cmpb $0x0, 0x85(%r15)
movq 0xbbf52(%rip), %rax     # 0x16b948
setne (%rax)
cmpb $0x0, 0x86(%r15)
movq 0xbbb40(%rip), %rax     # 0x16b548
setne (%rax)
cmpb $0x0, 0x9b(%r15)
movq 0xbbce6(%rip), %rax     # 0x16b700
setne (%rax)
cmpb $0x0, 0x8e(%r15)
movq 0xbbe34(%rip), %rax     # 0x16b860
setne (%rax)
cmpb $0x0, 0xb6(%r15)
movq 0xbc4aa(%rip), %rax     # 0x16bee8
setne (%rax)
cmpb $0x0, 0x90(%r15)
movq 0xbbfd0(%rip), %rax     # 0x16ba20
setne (%rax)
cmpb $0x0, 0x91(%r15)
movq 0xbc13e(%rip), %rax     # 0x16bba0
setne (%rax)
cmpb $0x0, 0x72(%r15)
movq 0xbb9af(%rip), %rax     # 0x16b420
setne (%rax)
cmpb $0x0, 0x92(%r15)
movq 0xbbf55(%rip), %rax     # 0x16b9d8
setne (%rax)
cmpb $0x0, 0x7b(%r15)
movq 0xbb9ee(%rip), %rax     # 0x16b480
setne (%rax)
cmpb $0x0, 0x98(%r15)
movq 0xbc094(%rip), %rax     # 0x16bb38
setne (%rax)
leaq 0x18(%rsp), %rdi
callq 0xc9b44
leaq 0x8(%rsp), %rdi
callq 0xc9b28
xorl %ebp, %ebp
movq 0xbbc04(%rip), %rax     # 0x16b6c8
addq $0x10, %rax
movq %rax, (%rbx)
movl %ebp, 0x8(%rbx)
movq %rbx, %rax
addq $0x40, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movb $0x1, 0xc6414(%rip)     # 0x175ef9
callq 0xc727a
movq 0xbba3f(%rip), %rcx     # 0x16b530
movl %eax, (%rcx)
movq 0xbbc6e(%rip), %rcx     # 0x16b768
movl %eax, (%rcx)
jmp 0xaf844
nop