// File: /workspace/github_c_makefile_star2_O0/mvermeulen[P]wspy/cpu_info.c
// Function: inventory_cpu
int inventory_cpu(void){
  unsigned int eax,ebx,ecx,edx;
  int i;
  int nwarn = 0;
  struct stat statbuf;
  FILE *fp;

  cpu_info = calloc(1,sizeof(struct cpu_info));

  // vendor string
  union cpuid0_vendor {
    struct { unsigned int ebx, edx, ecx; };
    char vendor[12];
  } cpuid_0;
  
  __cpuid(0,eax,ebx,ecx,edx);
  cpuid_0.ebx = ebx;
  cpuid_0.ecx = ecx;  
  cpuid_0.edx = edx;
  if (!strncmp(cpuid_0.vendor,"AuthenticAMD",12))
    cpu_info->vendor = VENDOR_AMD;
  else if (!strncmp(cpuid_0.vendor,"GenuineIntel",12))
    cpu_info->vendor = VENDOR_INTEL;
  else {
    cpu_info->vendor = VENDOR_UNKNOWN;
    warning("unknown cpu %16s\n",cpuid_0.vendor);
  }
  
  // model and family
  union cpuid1_modelinfo {
    struct {
      unsigned int step: 4;
      unsigned int model: 4;
      unsigned int family: 4;
      unsigned int ptype: 2;
      unsigned int pad1: 2;
      unsigned int emodel: 4;
      unsigned int efamily: 8;
      unsigned int pad2: 4;
    };
    unsigned int eax;
  } cpuid_1;

  __cpuid(1,eax,ebx,ecx,edx);
  cpuid_1.eax = eax;
  cpu_info->family = (cpuid_1.family==0xf)?
    cpuid_1.family+cpuid_1.efamily:
    cpuid_1.family;
  cpu_info->model = ((cpuid_1.family==0x6)||(cpuid_1.family==0xf))?
    (cpuid_1.emodel<<4) + cpuid_1.model:
    cpuid_1.model;

  // number of cores
  cpu_info->num_cores = get_nprocs();
  cpu_info->coreinfo = calloc(cpu_info->num_cores,
			      sizeof(struct cpu_core_info));

  // specify the core type
  for (i=0;i<cpu_info->num_cores;i++){
    if (cpu_info->vendor == VENDOR_AMD){
      if ((cpu_info->family == 0x17) || (cpu_info->family == 0x19)){
	// Zen
	cpu_info->coreinfo[i].vendor = CORE_AMD_ZEN;
      } else if (cpu_info->family == 0x1a) {
	// Zen5
	cpu_info->coreinfo[i].vendor = CORE_AMD_ZEN5;
      } else {
	cpu_info->coreinfo[i].vendor = CORE_AMD_UNKNOWN;
	if (nwarn == 0){
	  warning("unimplemented AMD CPU, family %x, model %x\n",
		  cpu_info->family,cpu_info->model);
	  nwarn++;
	}
      }
    } else if (cpu_info->vendor == VENDOR_INTEL){
      if ((cpu_info->family == 6) &&
	  ((cpu_info->model == 0xba)||(cpu_info->model == 0xb7)||
	   (cpu_info->model == 0x9a)||(cpu_info->model == 0x97)||
	   (cpu_info->model == 0xa7))){
	cpu_info->coreinfo[i].vendor = CORE_INTEL_CORE;
      } else {
	cpu_info->coreinfo[i].vendor = CORE_INTEL_UNKNOWN;
	if (nwarn == 0){
	  warning("unimplemented Intel CPU, family %x, model %x\n",
		  cpu_info->family,cpu_info->model);
	}
	nwarn++;
      }
    }
    cpu_info->coreinfo->is_available = 0;
    cpu_info->coreinfo->is_counter_started = 0;
  }
  // fix up hybrid cores for Raptor Lake and Alder Lake
  if (cpu_info->vendor == VENDOR_INTEL &&
      cpu_info->family == 6 &&
      ((cpu_info->model == 0xba)||(cpu_info->model == 0xb7)||
       (cpu_info->model == 0x9a)||(cpu_info->model == 0x97))){
    if (stat("/sys/devices/cpu_atom/cpus",&statbuf) != -1){
      cpu_info->is_hybrid = 1;
      if (fp = fopen("/sys/devices/cpu_atom/cpus","r")){
	int low,high;
	if (fscanf(fp,"%d-%d",&low,&high) == 2){
	  for (i=low;i<=high;i++){
	    cpu_info->coreinfo[i].vendor = CORE_INTEL_ATOM;
	  }
	}
	fclose(fp);
      }
    }
    if (stat("/sys/devices/cpu_core/cpus",&statbuf) != -1){
      if (fp = fopen("/sys/devices/cpu_core/cpus","r")){
	int low,high;
	if (fscanf(fp,"%d-%d",&low,&high) == 2){
	  for (i=low;i<=high;i++){
	    cpu_info->coreinfo[i].vendor = CORE_INTEL_CORE;
	  }
	}
	fclose(fp);
      }
    }    
  }
  // check affinity mask for available CPUs
  cpu_set_t set;
  cpu_info->num_cores_available;
  CPU_ZERO(&set);
  if (sched_getaffinity(getpid(),sizeof(set),&set) == -1){
    fatal("unable to get CPU affinity\n");
  }
  for (i=0;i<cpu_info->num_cores;i++){
    if (CPU_ISSET(i,&set)){
      cpu_info->coreinfo[i].is_available = 1;
      cpu_info->num_cores_available++;
    }
  }
  
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movl $0x0, -0x18(%rbp)
movl $0x1, %edi
movl $0x28, %esi
callq 0x31a0
movq %rax, 0x8de8(%rip)      # 0x14170
xorl %eax, %eax
xchgq %rbx, %rsi
cpuid
xchgq %rbx, %rsi
movl %esi, -0x160(%rbp)
movl %eax, %esi
movl -0x160(%rbp), %eax
movl %esi, -0x4(%rbp)
movl %eax, -0x8(%rbp)
movl %ecx, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl -0x8(%rbp), %eax
movl %eax, -0xbc(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0xb4(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0xb8(%rbp)
leaq -0xbc(%rbp), %rdi
leaq 0x4664(%rip), %rsi      # 0xfa39
movl $0xc, %edx
callq 0x3060
cmpl $0x0, %eax
jne 0xb3f3
movq 0x8d85(%rip), %rax      # 0x14170
movl $0x1, (%rax)
jmp 0xb443
leaq -0xbc(%rbp), %rdi
leaq 0x4645(%rip), %rsi      # 0xfa46
movl $0xc, %edx
callq 0x3060
cmpl $0x0, %eax
jne 0xb41f
movq 0x8d59(%rip), %rax      # 0x14170
movl $0x2, (%rax)
jmp 0xb441
movq 0x8d4a(%rip), %rax      # 0x14170
movl $0x0, (%rax)
leaq -0xbc(%rbp), %rsi
leaq 0x4619(%rip), %rdi      # 0xfa53
movb $0x0, %al
callq 0xbd10
jmp 0xb443
movl $0x1, %eax
xchgq %rbx, %rsi
cpuid
xchgq %rbx, %rsi
movl %esi, -0x164(%rbp)
movl %eax, %esi
movl -0x164(%rbp), %eax
movl %esi, -0x4(%rbp)
movl %eax, -0x8(%rbp)
movl %ecx, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl -0x4(%rbp), %eax
movl %eax, -0xc0(%rbp)
movl -0xc0(%rbp), %eax
shrl $0x8, %eax
andl $0xf, %eax
cmpl $0xf, %eax
jne 0xb4a9
movl -0xc0(%rbp), %eax
shrl $0x8, %eax
andl $0xf, %eax
movl -0xc0(%rbp), %ecx
shrl $0x14, %ecx
andl $0xff, %ecx
addl %ecx, %eax
movl %eax, -0x168(%rbp)
jmp 0xb4bb
movl -0xc0(%rbp), %eax
shrl $0x8, %eax
andl $0xf, %eax
movl %eax, -0x168(%rbp)
movl -0x168(%rbp), %ecx
movq 0x8ca8(%rip), %rax      # 0x14170
movl %ecx, 0x4(%rax)
movl -0xc0(%rbp), %eax
shrl $0x8, %eax
andl $0xf, %eax
cmpl $0x6, %eax
je 0xb4ed
movl -0xc0(%rbp), %eax
shrl $0x8, %eax
andl $0xf, %eax
cmpl $0xf, %eax
jne 0xb512
movl -0xc0(%rbp), %eax
shrl $0x10, %eax
andl $0xf, %eax
shll $0x4, %eax
movl -0xc0(%rbp), %ecx
shrl $0x4, %ecx
andl $0xf, %ecx
addl %ecx, %eax
movl %eax, -0x16c(%rbp)
jmp 0xb524
movl -0xc0(%rbp), %eax
shrl $0x4, %eax
andl $0xf, %eax
movl %eax, -0x16c(%rbp)
movl -0x16c(%rbp), %ecx
movq 0x8c3f(%rip), %rax      # 0x14170
movl %ecx, 0x8(%rax)
callq 0x3350
movl %eax, %ecx
movq 0x8c2e(%rip), %rax      # 0x14170
movl %ecx, 0xc(%rax)
movq 0x8c24(%rip), %rax      # 0x14170
movl 0xc(%rax), %eax
movl %eax, %edi
movl $0x60, %esi
callq 0x31a0
movq %rax, %rcx
movq 0x8c0b(%rip), %rax      # 0x14170
movq %rcx, 0x18(%rax)
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
movq 0x8bf6(%rip), %rcx      # 0x14170
cmpl 0xc(%rcx), %eax
jae 0xb764
movq 0x8be6(%rip), %rax      # 0x14170
cmpl $0x1, (%rax)
jne 0xb64c
movq 0x8bd6(%rip), %rax      # 0x14170
cmpl $0x17, 0x4(%rax)
je 0xb5ad
movq 0x8bc9(%rip), %rax      # 0x14170
cmpl $0x19, 0x4(%rax)
jne 0xb5cb
movq 0x8bbc(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x2, (%rax)
jmp 0xb647
movq 0x8b9e(%rip), %rax      # 0x14170
cmpl $0x1a, 0x4(%rax)
jne 0xb5f6
movq 0x8b91(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x3, (%rax)
jmp 0xb645
movq 0x8b73(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x1, (%rax)
cmpl $0x0, -0x18(%rbp)
jne 0xb643
movq 0x8b51(%rip), %rax      # 0x14170
movl 0x4(%rax), %esi
movq 0x8b47(%rip), %rax      # 0x14170
movl 0x8(%rax), %edx
leaq 0x4432(%rip), %rdi      # 0xfa65
movb $0x0, %al
callq 0xbd10
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xb645
jmp 0xb647
jmp 0xb728
movq 0x8b1d(%rip), %rax      # 0x14170
cmpl $0x2, (%rax)
jne 0xb726
movq 0x8b0d(%rip), %rax      # 0x14170
cmpl $0x6, 0x4(%rax)
jne 0xb6d7
movq 0x8b00(%rip), %rax      # 0x14170
cmpl $0xba, 0x8(%rax)
je 0xb6b9
movq 0x8af0(%rip), %rax      # 0x14170
cmpl $0xb7, 0x8(%rax)
je 0xb6b9
movq 0x8ae0(%rip), %rax      # 0x14170
cmpl $0x9a, 0x8(%rax)
je 0xb6b9
movq 0x8ad0(%rip), %rax      # 0x14170
cmpl $0x97, 0x8(%rax)
je 0xb6b9
movq 0x8ac0(%rip), %rax      # 0x14170
cmpl $0xa7, 0x8(%rax)
jne 0xb6d7
movq 0x8ab0(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x6, (%rax)
jmp 0xb724
movq 0x8a92(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x4, (%rax)
cmpl $0x0, -0x18(%rbp)
jne 0xb71b
movq 0x8a70(%rip), %rax      # 0x14170
movl 0x4(%rax), %esi
movq 0x8a66(%rip), %rax      # 0x14170
movl 0x8(%rax), %edx
leaq 0x437d(%rip), %rdi      # 0xfa91
movb $0x0, %al
callq 0xbd10
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xb726
jmp 0xb728
movq 0x8a41(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movb 0x4(%rax), %cl
andb $-0x2, %cl
orb $0x0, %cl
movb %cl, 0x4(%rax)
movq 0x8a2a(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movb 0x4(%rax), %cl
andb $-0x3, %cl
orb $0x0, %cl
movb %cl, 0x4(%rax)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xb570
movq 0x8a05(%rip), %rax      # 0x14170
cmpl $0x2, (%rax)
jne 0xb93c
movq 0x89f5(%rip), %rax      # 0x14170
cmpl $0x6, 0x4(%rax)
jne 0xb93c
movq 0x89e4(%rip), %rax      # 0x14170
cmpl $0xba, 0x8(%rax)
je 0xb7c9
movq 0x89d4(%rip), %rax      # 0x14170
cmpl $0xb7, 0x8(%rax)
je 0xb7c9
movq 0x89c4(%rip), %rax      # 0x14170
cmpl $0x9a, 0x8(%rax)
je 0xb7c9
movq 0x89b4(%rip), %rax      # 0x14170
cmpl $0x97, 0x8(%rax)
jne 0xb93c
leaq 0x42ef(%rip), %rdi      # 0xfabf
leaq -0xa8(%rbp), %rsi
callq 0x31f0
cmpl $-0x1, %eax
je 0xb88b
movq 0x8984(%rip), %rax      # 0x14170
movb 0x14(%rax), %cl
andb $-0x2, %cl
orb $0x1, %cl
movb %cl, 0x14(%rax)
leaq 0x42c0(%rip), %rdi      # 0xfabf
leaq 0x2b08(%rip), %rsi      # 0xe30e
callq 0x3270
movq %rax, -0xb0(%rbp)
cmpq $0x0, %rax
je 0xb889
movq -0xb0(%rbp), %rdi
leaq 0x42b4(%rip), %rsi      # 0xfada
leaq -0xc4(%rbp), %rdx
leaq -0xc8(%rbp), %rcx
movb $0x0, %al
callq 0x3070
cmpl $0x2, %eax
jne 0xb87d
movl -0xc4(%rbp), %eax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0xc8(%rbp), %eax
jg 0xb87b
movq 0x8915(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x5, (%rax)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xb849
jmp 0xb87d
movq -0xb0(%rbp), %rdi
callq 0x30b0
jmp 0xb88b
leaq 0x424e(%rip), %rdi      # 0xfae0
leaq -0xa8(%rbp), %rsi
callq 0x31f0
cmpl $-0x1, %eax
je 0xb93a
leaq 0x4232(%rip), %rdi      # 0xfae0
leaq 0x2a59(%rip), %rsi      # 0xe30e
callq 0x3270
movq %rax, -0xb0(%rbp)
cmpq $0x0, %rax
je 0xb938
movq -0xb0(%rbp), %rdi
leaq 0x4205(%rip), %rsi      # 0xfada
leaq -0xcc(%rbp), %rdx
leaq -0xd0(%rbp), %rcx
movb $0x0, %al
callq 0x3070
cmpl $0x2, %eax
jne 0xb92c
movl -0xcc(%rbp), %eax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0xd0(%rbp), %eax
jg 0xb92a
movq 0x8866(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x6, (%rax)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xb8f8
jmp 0xb92c
movq -0xb0(%rbp), %rdi
callq 0x30b0
jmp 0xb93a
jmp 0xb93c
leaq -0x150(%rbp), %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x3120
callq 0x30a0
movl %eax, %edi
movl $0x80, %esi
leaq -0x150(%rbp), %rdx
callq 0x32e0
cmpl $-0x1, %eax
jne 0xb97a
leaq 0x4188(%rip), %rdi      # 0xfafb
movb $0x0, %al
callq 0xbaf0
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
movq 0x87e5(%rip), %rcx      # 0x14170
cmpl 0xc(%rcx), %eax
jae 0xba53
movslq -0x14(%rbp), %rax
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rax
shrq $0x3, %rax
cmpq $0x80, %rax
jae 0xb9f2
movq -0x158(%rbp), %rax
shrq $0x6, %rax
movq -0x150(%rbp,%rax,8), %rax
movq -0x158(%rbp), %rcx
andq $0x3f, %rcx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x170(%rbp)
jmp 0xb9fc
xorl %eax, %eax
movl %eax, -0x170(%rbp)
jmp 0xb9fc
movl -0x170(%rbp), %eax
movl %eax, -0x15c(%rbp)
cmpl $0x0, -0x15c(%rbp)
je 0xba43
movq 0x8758(%rip), %rax      # 0x14170
movq 0x18(%rax), %rax
movslq -0x14(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movb 0x4(%rax), %cl
andb $-0x2, %cl
orb $0x1, %cl
movb %cl, 0x4(%rax)
movq 0x8736(%rip), %rax      # 0x14170
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x10(%rax)
jmp 0xba45
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0xb981
xorl %eax, %eax
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
nop