// File: /workspace/github_c_makefile_star2_O0/enzo1982[P]smooth/libraries/libcpuid/cpuid_main.c
// Function: cpuid_get_hypervisor
hypervisor_vendor_t cpuid_get_hypervisor(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{
	int i, r;
	uint32_t hypervisor_fn40000000h[NUM_REGS];
	char hypervisor_str[VENDOR_STR_MAX];
	struct cpu_id_t mydata;
	const struct { hypervisor_vendor_t hypervisor; char match[16]; }
	matchtable[NUM_HYPERVISOR_VENDORS] = {
		/* source: https://github.com/a0rtega/pafish/blob/master/pafish/cpu.c */
		{ HYPERVISOR_BHYVE      , "bhyve bhyve\0"   },
		{ HYPERVISOR_HYPERV     , "Microsoft Hv"    },
		{ HYPERVISOR_KVM        , "KVMKVMKVM\0\0\0" },
		{ HYPERVISOR_PARALLELS  , "prl hyperv\0\0"  },
		{ HYPERVISOR_QEMU       , "TCGTCGTCGTCG"    },
		{ HYPERVISOR_VIRTUALBOX , "VBoxVBoxVBox"    },
		{ HYPERVISOR_VMWARE     , "VMwareVMware"    },
		{ HYPERVISOR_XEN        , "XenVMMXenVMM"    },
	};

	if (!data) {
		if ((r = cpu_identify(raw, data)) < 0)
			return HYPERVISOR_UNKNOWN;
		data = &mydata;
	}

	/* Intel and AMD CPUs have reserved bit 31 of ECX of CPUID leaf 0x1 as the hypervisor present bit
	Source: https://kb.vmware.com/s/article/1009458 */
	switch (data->vendor) {
		case VENDOR_AMD:
		case VENDOR_INTEL:
			break;
		default:
			return HYPERVISOR_UNKNOWN;
	}
	if (!data->flags[CPU_FEATURE_HYPERVISOR])
		return HYPERVISOR_NONE;

	/* Intel and AMD have also reserved CPUID leaves 0x40000000 - 0x400000FF for software use.
	Hypervisors can use these leaves to provide an interface to pass information
	from the hypervisor to the guest operating system running inside a virtual machine.
	The hypervisor bit indicates the presence of a hypervisor
	and that it is safe to test these additional software leaves. */
	memset(hypervisor_fn40000000h, 0, sizeof(hypervisor_fn40000000h));
	hypervisor_fn40000000h[EAX] = 0x40000000;
	cpu_exec_cpuid_ext(hypervisor_fn40000000h);

	/* Copy the hypervisor CPUID information leaf */
	memcpy(hypervisor_str + 0, &hypervisor_fn40000000h[1], 4);
	memcpy(hypervisor_str + 4, &hypervisor_fn40000000h[2], 4);
	memcpy(hypervisor_str + 8, &hypervisor_fn40000000h[3], 4);
	hypervisor_str[12] = '\0';

	/* Determine hypervisor */
	for (i = 0; i < NUM_HYPERVISOR_VENDORS; i++)
		if (!strcmp(hypervisor_str, matchtable[i].match))
			return matchtable[i].hypervisor;
	return HYPERVISOR_UNKNOWN;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x22e0, %rsp           # imm = 0x22E0
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
leaq -0x22e0(%rbp), %rdi
leaq 0x71eaf(%rip), %rsi     # 0x1a6fe0
movl $0xb4, %edx
callq 0x593a0
cmpq $0x0, -0x18(%rbp)
jne 0x13516e
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x133850
movl %eax, -0x20(%rbp)
cmpl $0x0, %eax
jge 0x135163
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x135237
leaq -0x2220(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movl 0x54(%rax), %eax
subl $0x1, %eax
ja 0x13517e
jmp 0x13517c
jmp 0x13518a
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x135237
movq -0x18(%rbp), %rax
cmpb $0x0, 0xc9(%rax)
jne 0x1351a3
movl $0x0, -0x4(%rbp)
jmp 0x135237
leaq -0x30(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x5a200
movl $0x40000000, -0x30(%rbp) # imm = 0x40000000
leaq -0x30(%rbp), %rdi
callq 0x131740
movl -0x2c(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x28(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x38(%rbp)
movb $0x0, -0x34(%rbp)
movl $0x0, -0x1c(%rbp)
cmpl $0x9, -0x1c(%rbp)
jge 0x135230
leaq -0x40(%rbp), %rdi
movslq -0x1c(%rbp), %rax
leaq -0x22e0(%rbp), %rsi
imulq $0x14, %rax, %rax
addq %rax, %rsi
addq $0x4, %rsi
callq 0x5c440
cmpl $0x0, %eax
jne 0x135223
movslq -0x1c(%rbp), %rcx
leaq -0x22e0(%rbp), %rax
imulq $0x14, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl %eax, -0x4(%rbp)
jmp 0x135237
jmp 0x135225
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x1351e0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl -0x4(%rbp), %eax
addq $0x22e0, %rsp           # imm = 0x22E0
popq %rbp
retq
nopw %cs:(%rax,%rax)