// File: /workspace/github_c_makefile_star2_O1/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, 0xc68fb(%rip)     # 0x176ef9
jne 0xb061a
movq 0xbc0c1(%rip), %rax     # 0x16c6c8
addq $0x10, %rax
movq %rax, (%rbx)
movl $0x0, 0x8(%rbx)
jmp 0xb088d
cmpb $0x1, 0xc68d9(%rip)     # 0x176efa
jne 0xb063d
movq 0xbc09e(%rip), %rax     # 0x16c6c8
addq $0x10, %rax
movq %rax, (%rbx)
movl $0xffffffff, 0x8(%rbx)  # imm = 0xFFFFFFFF
jmp 0xb088d
callq 0xc8220
testl %eax, %eax
je 0xb089d
movb $0x1, 0xc68a9(%rip)     # 0x176efa
leaq 0x8(%rsp), %rdi
callq 0xc83da
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
testl %eax, %eax
js 0xb087c
leaq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0xc9915
testl %eax, %eax
js 0xb087c
movb $0x1, 0xc6873(%rip)     # 0x176ef9
movb $0x0, 0xc686d(%rip)     # 0x176efa
movq 0x20(%rsp), %r15
leaq 0x4(%r15), %rsi
movq 0xbc003(%rip), %rdi     # 0x16c6a0
callq 0x55f40
leaq 0x14(%r15), %rsi
movq 0xbc143(%rip), %r14     # 0x16c7f0
movq %r14, %rdi
callq 0x55f40
xorl %ebp, %ebp
movq %r14, %rdi
xorl %esi, %esi
callq 0x55260
testb %al, %al
je 0xb06d8
leaq 0x150(%r15), %rsi
movq 0xbc11d(%rip), %rdi     # 0x16c7f0
callq 0x55f40
movq 0xbbe51(%rip), %r12     # 0x16c530
movl %ebp, (%r12)
movq 0xbc07e(%rip), %r14     # 0x16c768
movl %ebp, (%r14)
movzbl 0x18(%rsp), %esi
testq %rsi, %rsi
je 0xb072d
movl (%r14), %eax
movl (%r12), %ecx
movq 0x20(%rsp), %rdx
imulq $0x21e0, %rsi, %rsi     # imm = 0x21E0
xorl %edi, %edi
addl 0xec(%rdx,%rdi), %ecx
movl %ecx, (%r12)
addl 0xf0(%rdx,%rdi), %eax
movl %eax, (%r14)
addq $0x21e0, %rdi           # imm = 0x21E0
cmpq %rdi, %rsi
jne 0xb070c
callq 0xc8216
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 0xbbd53(%rip), %rax     # 0x16c4a8
setne (%rax)
cmpb $0x0, 0x8f(%r15)
movq 0xbc751(%rip), %rax     # 0x16ceb8
setne (%rax)
cmpb $0x0, 0x6f(%r15)
movq 0xbbc62(%rip), %rax     # 0x16c3d8
setne (%rax)
cmpb $0x0, 0x70(%r15)
movq 0xbc12b(%rip), %rax     # 0x16c8b0
setne (%rax)
cmpb $0x0, 0x76(%r15)
movq 0xbc504(%rip), %rax     # 0x16cc98
setne (%rax)
cmpb $0x0, 0x7f(%r15)
movq 0xbbdad(%rip), %rax     # 0x16c550
setne (%rax)
cmpb $0x0, 0x85(%r15)
movq 0xbc193(%rip), %rax     # 0x16c948
setne (%rax)
cmpb $0x0, 0x86(%r15)
movq 0xbbd81(%rip), %rax     # 0x16c548
setne (%rax)
cmpb $0x0, 0x9b(%r15)
movq 0xbbf27(%rip), %rax     # 0x16c700
setne (%rax)
cmpb $0x0, 0x8e(%r15)
movq 0xbc075(%rip), %rax     # 0x16c860
setne (%rax)
cmpb $0x0, 0xb6(%r15)
movq 0xbc6eb(%rip), %rax     # 0x16cee8
setne (%rax)
cmpb $0x0, 0x90(%r15)
movq 0xbc211(%rip), %rax     # 0x16ca20
setne (%rax)
cmpb $0x0, 0x91(%r15)
movq 0xbc37f(%rip), %rax     # 0x16cba0
setne (%rax)
cmpb $0x0, 0x72(%r15)
movq 0xbbbf0(%rip), %rax     # 0x16c420
setne (%rax)
cmpb $0x0, 0x92(%r15)
movq 0xbc196(%rip), %rax     # 0x16c9d8
setne (%rax)
cmpb $0x0, 0x7b(%r15)
movq 0xbbc2f(%rip), %rax     # 0x16c480
setne (%rax)
cmpb $0x0, 0x98(%r15)
movq 0xbc2d5(%rip), %rax     # 0x16cb38
setne (%rax)
leaq 0x18(%rsp), %rdi
callq 0xca91f
leaq 0x8(%rsp), %rdi
callq 0xca903
xorl %ebp, %ebp
movq 0xbbe45(%rip), %rax     # 0x16c6c8
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, 0xc6655(%rip)     # 0x176ef9
callq 0xc8216
movq 0xbbc80(%rip), %rcx     # 0x16c530
movl %eax, (%rcx)
movq 0xbbeaf(%rip), %rcx     # 0x16c768
movl %eax, (%rcx)
jmp 0xb0600