// File: /workspace/github_c_makefile_star2_O2/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 %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdi, %rbx
cmpb $0x1, 0xc1725(%rip)     # 0x16c0b9
jne 0xaa9ad
movq 0xb6d2b(%rip), %rax     # 0x1616c8
addq $0x10, %rax
movq %rax, (%rbx)
andl $0x0, 0x8(%rbx)
jmp 0xaac34
cmpb $0x1, 0xc1706(%rip)     # 0x16c0ba
jne 0xaa9cd
movq 0xb6d0b(%rip), %rax     # 0x1616c8
addq $0x10, %rax
movq %rax, (%rbx)
orl $-0x1, 0x8(%rbx)
jmp 0xaac34
callq 0xc0d78
testl %eax, %eax
je 0xaaab3
movb $0x1, 0xc16d9(%rip)     # 0x16c0ba
movq %rsp, %rdi
callq 0xc0f23
pushq $-0x1
popq %rbp
testl %eax, %eax
js 0xaac23
movq %rsp, %rdi
leaq 0x10(%rsp), %rsi
callq 0xc24d1
testl %eax, %eax
js 0xaac23
movb $0x1, 0xc16a9(%rip)     # 0x16c0b9
movb $0x0, 0xc16a3(%rip)     # 0x16c0ba
movq 0x18(%rsp), %r15
leaq 0x4(%r15), %rsi
movq 0xb6c79(%rip), %rdi     # 0x1616a0
callq 0x57010
leaq 0x14(%r15), %rsi
movq 0xb6db9(%rip), %r14     # 0x1617f0
movq %r14, %rdi
callq 0x57010
xorl %r12d, %r12d
movq %r14, %rdi
xorl %esi, %esi
callq 0x56280
testb %al, %al
je 0xaaa63
leaq 0x150(%r15), %rsi
movq 0xb6d92(%rip), %rdi     # 0x1617f0
callq 0x57010
movq 0xb6ac6(%rip), %r13     # 0x161530
andl $0x0, (%r13)
movq 0xb6cf2(%rip), %r14     # 0x161768
andl $0x0, (%r14)
movzbl 0x10(%rsp), %ecx
movq 0x18(%rsp), %rax
imulq $0x21e0, %rcx, %rcx     # imm = 0x21E0
xorl %edx, %edx
xorl %esi, %esi
cmpq %rdx, %rcx
je 0xaaad6
addl 0xec(%rax,%rdx), %esi
movl %esi, (%r13)
addl 0xf0(%rax,%rdx), %r12d
movl %r12d, (%r14)
addq $0x21e0, %rdx           # imm = 0x21E0
jmp 0xaaa8f
movb $0x1, 0xc15ff(%rip)     # 0x16c0b9
callq 0xc0d6e
movq 0xb6a6a(%rip), %rcx     # 0x161530
movl %eax, (%rcx)
movq 0xb6c99(%rip), %rcx     # 0x161768
movl %eax, (%rcx)
jmp 0xaa996
callq 0xc0d6e
movl (%r14), %ecx
cltd
idivl %ecx
movl (%r13), %edx
imull %eax, %edx
movl %edx, (%r13)
imull %ecx, %eax
movl %eax, (%r14)
cmpb $0x0, 0x6d(%r15)
movq 0xb69aa(%rip), %rax     # 0x1614a8
setne (%rax)
cmpb $0x0, 0x8f(%r15)
movq 0xb73a8(%rip), %rax     # 0x161eb8
setne (%rax)
cmpb $0x0, 0x6f(%r15)
movq 0xb68b9(%rip), %rax     # 0x1613d8
setne (%rax)
cmpb $0x0, 0x70(%r15)
movq 0xb6d82(%rip), %rax     # 0x1618b0
setne (%rax)
cmpb $0x0, 0x76(%r15)
movq 0xb715b(%rip), %rax     # 0x161c98
setne (%rax)
cmpb $0x0, 0x7f(%r15)
movq 0xb6a04(%rip), %rax     # 0x161550
setne (%rax)
cmpb $0x0, 0x85(%r15)
movq 0xb6dea(%rip), %rax     # 0x161948
setne (%rax)
cmpb $0x0, 0x86(%r15)
movq 0xb69d8(%rip), %rax     # 0x161548
setne (%rax)
cmpb $0x0, 0x9b(%r15)
movq 0xb6b7e(%rip), %rax     # 0x161700
setne (%rax)
cmpb $0x0, 0x8e(%r15)
movq 0xb6ccc(%rip), %rax     # 0x161860
setne (%rax)
cmpb $0x0, 0xb6(%r15)
movq 0xb7342(%rip), %rax     # 0x161ee8
setne (%rax)
cmpb $0x0, 0x90(%r15)
movq 0xb6e68(%rip), %rax     # 0x161a20
setne (%rax)
cmpb $0x0, 0x91(%r15)
movq 0xb6fd6(%rip), %rax     # 0x161ba0
setne (%rax)
cmpb $0x0, 0x72(%r15)
movq 0xb6847(%rip), %rax     # 0x161420
setne (%rax)
cmpb $0x0, 0x92(%r15)
movq 0xb6ded(%rip), %rax     # 0x1619d8
setne (%rax)
cmpb $0x0, 0x7b(%r15)
movq 0xb6886(%rip), %rax     # 0x161480
setne (%rax)
cmpb $0x0, 0x98(%r15)
movq 0xb6f2c(%rip), %rax     # 0x161b38
setne (%rax)
leaq 0x10(%rsp), %rdi
callq 0xc33bf
movq %rsp, %rdi
callq 0xc33a4
xorl %ebp, %ebp
movq 0xb6a9e(%rip), %rax     # 0x1616c8
addq $0x10, %rax
movq %rax, (%rbx)
movl %ebp, 0x8(%rbx)
movq %rbx, %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq