// File: /workspace/github_c_makefile_star2_O2/enzo1982[P]smooth/libraries/libcpuid/cpuid_main.c
// Function: cpu_identify_all
int cpu_identify_all(struct cpu_raw_data_array_t* raw_array, struct system_id_t* system)
{
	int cur_error = cpuid_set_error(ERR_OK);
	int ret_error = cpuid_set_error(ERR_OK);
	double smt_divisor;
	bool is_new_cpu_type;
	bool is_last_item;
	bool is_smt_supported;
	bool is_apic_supported = true;
	uint8_t cpu_type_index = 0;
	int32_t num_logical_cpus = 0;
	int32_t cur_package_id = 0;
	int32_t prev_package_id = 0;
	logical_cpu_t logical_cpu = 0;
	cpu_purpose_t purpose;
	cpu_affinity_mask_t affinity_mask;
	struct cpu_raw_data_array_t my_raw_array;
	struct internal_id_info_t id_info;
	struct internal_apic_info_t apic_info;
	struct internal_core_instances_t cores_type;
	struct internal_cache_instances_t caches_type, caches_all;

	if (system == NULL)
		return cpuid_set_error(ERR_HANDLE);
	if (!raw_array) {
		if ((ret_error = cpuid_get_all_raw_data(&my_raw_array)) < 0)
			return cpuid_set_error(ret_error);
		raw_array = &my_raw_array;
	}
	system_id_t_constructor(system);
	core_instances_t_constructor(&cores_type);
	cache_instances_t_constructor(&caches_type);
	cache_instances_t_constructor(&caches_all);
	if (raw_array->with_affinity)
		init_affinity_mask(&affinity_mask);

	/* Iterate over all raw */
	for (logical_cpu = 0; logical_cpu < raw_array->num_raw; logical_cpu++) {
		is_new_cpu_type = false;
		is_last_item    = (logical_cpu + 1 >= raw_array->num_raw);
		debugf(2, "Identifying logical core %u\n", logical_cpu);
		/* Get CPU purpose and APIC ID
		   For hybrid CPUs, the purpose may be different than the previous iteration (e.g. from P-cores to E-cores)
		   APIC ID are unique for each logical CPU cores.
		*/
		purpose = cpu_ident_purpose(&raw_array->raw[logical_cpu]);
		if (raw_array->with_affinity && is_apic_supported) {
			is_apic_supported = cpu_ident_apic_id(logical_cpu, &raw_array->raw[logical_cpu], &apic_info);
			if (is_apic_supported)
				cur_package_id = apic_info.package_id;
		}

		/* Put data to system->cpu_types on the first iteration or when purpose is different than previous core */
		if ((system->num_cpu_types == 0) || (purpose != system->cpu_types[system->num_cpu_types - 1].purpose) || (cur_package_id != prev_package_id)) {
			is_new_cpu_type = true;
			cpu_type_index  = system->num_cpu_types;
			cpuid_grow_system_id(system, system->num_cpu_types + 1);
			cur_error = cpu_ident_internal(&raw_array->raw[logical_cpu], &system->cpu_types[cpu_type_index], &id_info);
			if (ret_error == ERR_OK)
				ret_error = cur_error;
		}
		/* Increment counters only for current purpose */
		if (raw_array->with_affinity && ((logical_cpu == 0) || !is_new_cpu_type)) {
			set_affinity_mask_bit(logical_cpu, &affinity_mask);
			num_logical_cpus++;
			if (is_apic_supported) {
				update_core_instances(&cores_type, &apic_info);
				update_cache_instances(&caches_type, &apic_info, &id_info, true);
				update_cache_instances(&caches_all,  &apic_info, &id_info, false);
			}
		}

		/* Update logical CPU counters, physical CPU counters and cache instance in system->cpu_types
		   Note: we need to differenciate two events:
		     - is_new_cpu_type (e.g. purpose was 'efficiency' during previous loop, and now purpose is 'performance')
		     - is_last_item (i.e. this is the last iteration in raw_array->num_raw)
		   In some cases, both events can occur during the same iteration, thus we have to update counters twice for the same logical_cpu.
		   This occurs with single-core CPU type. For instance, Pentacore Lakefield CPU consists of:
		     - 1 "big" Sunny Cove core
		     - 4 "little" Tremont cores
		   On the last iteration, there is no need to reset values for the next purpose.
		*/
		if (raw_array->with_affinity && (is_last_item || (is_new_cpu_type && (system->num_cpu_types > 1)))) {
			enum event_t {
				EVENT_NEW_CPU_TYPE = 0,
				EVENT_LAST_ITEM    = 1
			};
			const enum event_t first_event = is_new_cpu_type && (system->num_cpu_types > 1) ? EVENT_NEW_CPU_TYPE : EVENT_LAST_ITEM;
			const enum event_t last_event  = is_last_item                                   ? EVENT_LAST_ITEM    : EVENT_NEW_CPU_TYPE;
			enum event_t event;
			for (event = first_event; event <= last_event; event++) {
				switch (event) {
					case EVENT_NEW_CPU_TYPE: cpu_type_index = system->num_cpu_types - 2; break;
					case EVENT_LAST_ITEM:    cpu_type_index = system->num_cpu_types - 1; break;
					default: warnf("Warning: event %i in cpu_identify_all() not handled.\n", event); return cpuid_set_error(ERR_NOT_IMP);
				}
				copy_affinity_mask(&system->cpu_types[cpu_type_index].affinity_mask, &affinity_mask);
				if (event != EVENT_LAST_ITEM) {
					init_affinity_mask(&affinity_mask);
					set_affinity_mask_bit(logical_cpu, &affinity_mask);
				}
				if (is_apic_supported) {
					system->cpu_types[cpu_type_index].num_cores                = cores_type.instances;
					system->cpu_types[cpu_type_index].l1_instruction_instances = caches_type.instances[L1I];
					system->cpu_types[cpu_type_index].l1_data_instances        = caches_type.instances[L1D];
					system->cpu_types[cpu_type_index].l2_instances             = caches_type.instances[L2];
					system->cpu_types[cpu_type_index].l3_instances             = caches_type.instances[L3];
					system->cpu_types[cpu_type_index].l4_instances             = caches_type.instances[L4];
					if (event != EVENT_LAST_ITEM) {
						core_instances_t_constructor(&cores_type);
						cache_instances_t_constructor(&caches_type);
						update_core_instances(&cores_type, &apic_info);
						update_cache_instances(&caches_type, &apic_info, &id_info, true);
						update_cache_instances(&caches_all,  &apic_info, &id_info, false);
					}
				}
				else {
					/* Note: if SMT is disabled by BIOS, smt_divisor will no reflect the current state properly */
					is_smt_supported = system->cpu_types[cpu_type_index].num_cores > 0 ? (system->cpu_types[cpu_type_index].num_logical_cpus % system->cpu_types[cpu_type_index].num_cores) == 0 : false;
					smt_divisor      = is_smt_supported ? system->cpu_types[cpu_type_index].num_logical_cpus / system->cpu_types[cpu_type_index].num_cores : 1.0;
					system->cpu_types[cpu_type_index].num_cores = (int32_t) (num_logical_cpus / smt_divisor);
				}
				/* Save current values in system->cpu_types[cpu_type_index] and reset values for the next purpose */
				system->cpu_types[cpu_type_index].num_logical_cpus = num_logical_cpus;
				num_logical_cpus = 1;
			}
		}
		prev_package_id = cur_package_id;
	}

	/* Update the grand total of cache instances */
	if (is_apic_supported) {
		system->l1_instruction_total_instances = caches_all.instances[L1I];
		system->l1_data_total_instances        = caches_all.instances[L1D];
		system->l2_total_instances             = caches_all.instances[L2];
		system->l3_total_instances             = caches_all.instances[L3];
		system->l4_total_instances             = caches_all.instances[L4];
	}

	/* Update the total_logical_cpus value for each purpose */
	for (cpu_type_index = 0; cpu_type_index < system->num_cpu_types; cpu_type_index++)
		system->cpu_types[cpu_type_index].total_logical_cpus = logical_cpu;

	return ret_error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78e8, %rsp           # imm = 0x78E8
movq %rsi, %rbx
movq %rdi, %r12
leaq 0x9ee41(%rip), %rdi     # 0x161330
callq 0x57820
leaq 0x30(%rax), %rax
movq %rax, 0x40(%rsp)
andl $0x0, (%rax)
testq %rbx, %rbx
je 0xc2bf9
xorl %eax, %eax
testq %r12, %r12
jne 0xc252b
leaq 0xc0(%rsp), %r12
movq %r12, %rdi
callq 0xc0f23
testl %eax, %eax
js 0xc2bfc
movl %eax, 0x1c(%rsp)
xorl %r14d, %r14d
movb %r14b, (%rbx)
andq $0x0, 0x8(%rbx)
orl $-0x1, 0x20(%rbx)
pcmpeqd %xmm0, %xmm0
movdqu %xmm0, 0x10(%rbx)
leaq 0xd8(%rsp), %rdi
movb %r14b, -0x4(%rdi)
movl $0x800, %edx            # imm = 0x800
xorl %esi, %esi
callq 0x56ff0
leaq 0x8e0(%rsp), %rdi
movb %r14b, -0x4(%rdi)
andl $0x0, -0x8(%rdi)
movl $0x2800, %edx           # imm = 0x2800
xorl %esi, %esi
callq 0x56ff0
leaq 0x30e8(%rsp), %rdi
movb %r14b, -0x4(%rdi)
andl $0x0, -0x8(%rdi)
movl $0x2800, %edx           # imm = 0x2800
xorl %esi, %esi
callq 0x56ff0
cmpb $0x1, (%r12)
jne 0xc25ab
leaq 0x58e8(%rsp), %rdi
callq 0xc3c12
movb $0x1, %al
movl %eax, 0x4(%rsp)
movl $0x484, %eax            # imm = 0x484
movq %rax, 0x10(%rsp)
movl $0x48c, %eax            # imm = 0x48C
movq %rax, 0x48(%rsp)
leaq 0x58e8(%rsp), %rbp
xorl %r14d, %r14d
movl $0x0, 0x18(%rsp)
xorl %r13d, %r13d
movq %r12, 0x28(%rsp)
movzwl 0x2(%r12), %eax
movq %rax, 0x30(%rsp)
cmpq %rax, %r14
jae 0xc2b9e
movl %r13d, %r15d
pushq $0x2
popq %rdi
leaq 0x414b0(%rip), %rsi     # 0x103ab1
movl %r14d, %edx
xorl %eax, %eax
callq 0xc34c6
imulq $0x580, %r14, %rcx      # imm = 0x580
movq 0x8(%r12), %rdi
movq %rcx, 0x38(%rsp)
addq %rcx, %rdi
callq 0xc2c15
cmpb $0x1, (%r12)
movq %r14, 0x20(%rsp)
jne 0xc2710
testb $0x1, 0x4(%rsp)
je 0xc2710
movl %eax, 0xc(%rsp)
movq 0x8(%r12), %r13
leaq 0x60(%rsp), %rax
andq $0x0, 0x10(%rax)
movq 0x38(%rsp), %rcx
leaq (%rcx,%r13), %r14
pxor %xmm0, %xmm0
movdqu %xmm0, (%rax)
pcmpeqd %xmm0, %xmm0
movdqa %xmm0, 0x50(%rsp)
movq 0x20(%rsp), %rax
movw %ax, 0x74(%rsp)
movq %r14, %rdi
leaq 0xb0(%rsp), %rsi
callq 0xc3065
cmpl $0x2, %eax
jae 0xc26e3
cmpl $0xb, (%r14)
jb 0xc26f3
cmpw $0x0, 0xb4(%r14)
je 0xc26f3
movq 0x10(%rsp), %rax
addq %r13, %rax
xorl %edx, %edx
xorl %ecx, %ecx
leaq 0x58(%rsp), %r9
leaq 0x5c(%rsp), %r10
pushq $-0x1
popq %r11
movl -0x4(%rax), %esi
testl %esi, %esi
je 0xc2b17
cmpq $0x3, %rdx
ja 0xc2b17
cmpl $0x0, (%rax)
je 0xc2b17
andl $0x1f, %esi
incq %rdx
addq $0x10, %rax
movl %esi, %ecx
jmp 0xc26b7
cmpl $-0x1, %eax
jne 0xc26f3
movq 0x40(%rsp), %rax
movl $0xfffffff9, (%rax)     # imm = 0xFFFFFFF9
movl $0x0, 0x4(%rsp)
leaq 0x41e6e(%rip), %rdi     # 0x104570
xorl %eax, %eax
callq 0xc340e
movl %r15d, %r13d
movl 0xc(%rsp), %eax
movzbl (%rbx), %r14d
testq %r14, %r14
je 0xc273e
movq 0x8(%rbx), %rdx
leal -0x1(%r14), %ecx
imulq $0x21e0, %rcx, %rcx     # imm = 0x21E0
cmpl 0x21d8(%rdx,%rcx), %eax
jne 0xc274b
cmpl %r15d, %r13d
jne 0xc274b
xorl %r15d, %r15d
jmp 0xc282c
movb $0x1, %r12b
pushq $0x1
popq %rcx
movq 0x10(%rsp), %r15
jmp 0xc2761
movl %r14d, %eax
incb %al
je 0xc27fa
movzbl %al, %ecx
movq 0x10(%rsp), %r15
movl %eax, %r12d
pushq $0x3
popq %rdi
leaq 0x41e86(%rip), %rsi     # 0x1045f1
movl %r14d, %edx
xorl %eax, %eax
callq 0xc34c6
movq 0x8(%rbx), %rdi
movb %r12b, 0xb(%rsp)
movzbl %r12b, %r12d
imulq $0x21e0, %r12, %rsi     # imm = 0x21E0
callq 0x56410
testq %rax, %rax
je 0xc27ea
movl %r13d, 0xc(%rsp)
movq %r15, 0x10(%rsp)
movzbl (%rbx), %r15d
imulq $0x21e0, %r15, %r13     # imm = 0x21E0
movq %rax, 0x80(%rsp)
addq %rax, %r13
cmpq %r12, %r15
jae 0xc27cc
movq %r13, %rdi
callq 0xc2460
incq %r15
addq $0x21e0, %r13           # imm = 0x21E0
jmp 0xc27b3
movb 0xb(%rsp), %al
movb %al, (%rbx)
movq 0x80(%rsp), %rax
movq %rax, 0x8(%rbx)
movq 0x28(%rsp), %r12
movl 0xc(%rsp), %r13d
jmp 0xc27fa
movq 0x40(%rsp), %rax
movl $0xfffffffd, (%rax)     # imm = 0xFFFFFFFD
movq 0x28(%rsp), %r12
movq 0x38(%rsp), %rdi
addq 0x8(%r12), %rdi
imulq $0x21e0, %r14, %rsi     # imm = 0x21E0
addq 0x8(%rbx), %rsi
leaq 0x88(%rsp), %rdx
callq 0xc209c
movl 0x1c(%rsp), %ecx
testl %ecx, %ecx
cmovel %eax, %ecx
movl %ecx, 0x1c(%rsp)
movb $0x1, %r15b
movq 0x20(%rsp), %r14
testq %r14, %r14
setne %al
testb %r15b, %al
jne 0xc28af
cmpb $0x0, (%r12)
je 0xc28af
movzwl %r14w, %edi
movq %rbp, %rsi
callq 0xc3c28
incl 0x18(%rsp)
testb $0x1, 0x4(%rsp)
je 0xc28af
leaq 0xd4(%rsp), %rdi
movl %r13d, %r12d
leaq 0x50(%rsp), %r13
movq %r13, %rsi
callq 0xc2c86
leaq 0x8d8(%rsp), %rdi
movq %r13, %rsi
leaq 0x88(%rsp), %rdx
pushq $0x1
popq %rcx
callq 0xc2cd2
leaq 0x30e0(%rsp), %rdi
movq %r13, %rsi
movl %r12d, %r13d
movq 0x28(%rsp), %r12
leaq 0x88(%rsp), %rdx
xorl %ecx, %ecx
callq 0xc2cd2
cmpb $0x1, (%r12)
jne 0xc2ad6
leal 0x1(%r14), %eax
cmpl 0x30(%rsp), %eax
jb 0xc28de
pushq $0x1
popq %r14
testb %r15b, %r15b
movq 0x10(%rsp), %rcx
je 0xc28f8
xorl %r14d, %r14d
cmpb $0x2, (%rbx)
setb %r14b
jmp 0xc28f8
testb %r15b, %r15b
je 0xc2ad6
xorl %r14d, %r14d
cmpb $0x1, (%rbx)
movq 0x10(%rsp), %rcx
jbe 0xc2b10
movl %r13d, 0xc(%rsp)
movq %rcx, 0x10(%rsp)
xorl %ecx, %ecx
cmpl 0x30(%rsp), %eax
setae %cl
movl %ecx, 0x38(%rsp)
movzwl 0x20(%rsp), %eax
movl %eax, 0x30(%rsp)
movl 0x18(%rsp), %r15d
movl 0x4(%rsp), %r12d
cmpl 0x38(%rsp), %r14d
ja 0xc2add
testl %r14d, %r14d
sete %al
notb %al
addb (%rbx), %al
movq 0x8(%rbx), %rcx
movzbl %al, %eax
imulq $0x21e0, %rax, %r13     # imm = 0x21E0
leaq (%rcx,%r13), %rdi
addq $0x1d8, %rdi            # imm = 0x1D8
movq %rbp, %rsi
callq 0xc3c1e
cmpl $0x1, %r14d
je 0xc2972
movq %rbp, %rdi
callq 0xc3c12
movl 0x30(%rsp), %edi
movq %rbp, %rsi
callq 0xc3c28
testb $0x1, %r12b
je 0xc2a78
movzbl 0xd4(%rsp), %eax
movq 0x8(%rbx), %rcx
movl %eax, 0xec(%rcx,%r13)
movd 0x8d8(%rsp), %xmm0
pxor %xmm1, %xmm1
punpcklbw %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
punpcklwd %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
pshufd $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movdqu %xmm0, 0x13c(%rcx,%r13)
movzbl 0x8dc(%rsp), %eax
movl %eax, 0x14c(%rcx,%r13)
cmpl $0x1, %r14d
je 0xc2ac2
xorl %r12d, %r12d
movb %r12b, 0xd4(%rsp)
movl $0x800, %edx            # imm = 0x800
leaq 0xd8(%rsp), %rdi
xorl %esi, %esi
callq 0x56ff0
movb %r12b, 0x8dc(%rsp)
andl $0x0, 0x8d8(%rsp)
movl $0x2800, %edx           # imm = 0x2800
leaq 0x8e0(%rsp), %rdi
xorl %esi, %esi
callq 0x56ff0
leaq 0xd4(%rsp), %rdi
leaq 0x50(%rsp), %r12
movq %r12, %rsi
callq 0xc2c86
leaq 0x8d8(%rsp), %rdi
movq %r12, %rsi
movl %r15d, %r12d
movq %rbx, %r15
movq %rbp, %rbx
leaq 0x88(%rsp), %rbp
movq %rbp, %rdx
pushq $0x1
popq %rcx
callq 0xc2cd2
leaq 0x30e0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movq %rbp, %rdx
movq %rbx, %rbp
movq %r15, %rbx
movl %r12d, %r15d
movl 0x4(%rsp), %r12d
xorl %ecx, %ecx
callq 0xc2cd2
movq 0x8(%rbx), %rcx
jmp 0xc2ac2
movq 0x8(%rbx), %rcx
movl 0xec(%rcx,%r13), %esi
movsd 0x208e4(%rip), %xmm0    # 0xe3370
testl %esi, %esi
jle 0xc2aad
leaq (%rcx,%r13), %rax
movl 0xf0(%rax), %eax
cltd
idivl %esi
movsd 0x208cb(%rip), %xmm0    # 0xe3370
testl %edx, %edx
jne 0xc2aad
cvtsi2sd %eax, %xmm0
cvtsi2sd %r15d, %xmm1
divsd %xmm0, %xmm1
cvttsd2si %xmm1, %eax
movl %eax, 0xec(%rcx,%r13)
movl %r15d, 0xf0(%rcx,%r13)
incl %r14d
pushq $0x1
popq %r15
jmp 0xc2922
movq 0x10(%rsp), %rcx
jmp 0xc2af6
movl %r15d, 0x18(%rsp)
movq 0x28(%rsp), %r12
movq 0x20(%rsp), %r14
movq 0x10(%rsp), %rcx
movl 0xc(%rsp), %r13d
incq %r14
movl $0x580, %eax            # imm = 0x580
addq %rax, %rcx
movq %rcx, 0x10(%rsp)
addq %rax, 0x48(%rsp)
jmp 0xc25e0
movq 0x20(%rsp), %r14
jmp 0xc2af6
movl %r11d, %r14d
shll %cl, %r14d
addq 0x48(%rsp), %r13
xorl %eax, %eax
movl %r11d, %esi
xorl %edx, %edx
movl -0xc(%r13), %ecx
testl %ecx, %ecx
je 0xc2b7d
cmpq $0x3, %rax
ja 0xc2b7d
cmpl $0x0, -0x8(%r13)
je 0xc2b7d
movzbl -0x3(%r13), %edx
movl (%r13), %esi
cmpl $0x2, %edx
je 0xc2b62
cmpl $0x1, %edx
jne 0xc2b74
movl %r11d, %r8d
shll %cl, %r8d
notl %r8d
movq %r10, %rcx
movl %r8d, %edi
jmp 0xc2b6e
movl %r14d, %r8d
xorl %edi, %r8d
notl %r8d
movq %r9, %rcx
andl %esi, %r8d
movl %r8d, (%rcx)
incq %rax
addq $0x10, %r13
jmp 0xc2b29
movl %esi, 0x50(%rsp)
andl %esi, %r14d
movl %r14d, 0x54(%rsp)
testb %dl, %dl
setne %al
movl %eax, 0x4(%rsp)
cmovel %r15d, %r14d
movl %r14d, %r13d
jmp 0xc270c
testb $0x1, 0x4(%rsp)
je 0xc2bcf
movd 0x30e0(%rsp), %xmm0
pxor %xmm1, %xmm1
punpcklbw %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
punpcklwd %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
pshufd $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movdqu %xmm0, 0x10(%rbx)
movzbl 0x30e4(%rsp), %eax
movl %eax, 0x20(%rbx)
movzbl (%rbx), %eax
imulq $0x21e0, %rax, %rsi     # imm = 0x21E0
xorl %ecx, %ecx
movl 0x1c(%rsp), %eax
cmpq %rcx, %rsi
je 0xc2c03
movq 0x8(%rbx), %rdx
movl %r14d, 0xf4(%rdx,%rcx)
addq $0x21e0, %rcx           # imm = 0x21E0
jmp 0xc2bdf
pushq $-0xc
popq %rax
movq 0x40(%rsp), %rcx
movl %eax, (%rcx)
addq $0x78e8, %rsp           # imm = 0x78E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq