#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */
typedef struct TYPE_2__ TYPE_1__;

/* Type definitions */
struct kvm_cpuid2 {
  int nent;
  TYPE_1__ *entries;
};
typedef int /*<<< orphan*/ __u32;
struct TYPE_2__ {
  int /*<<< orphan*/ edx;
  int /*<<< orphan*/ ecx;
  int /*<<< orphan*/ ebx;
  int /*<<< orphan*/ eax;
  int /*<<< orphan*/ flags;
  int /*<<< orphan*/ index;
  int /*<<< orphan*/ function;
};

/* Variables and functions */
int E2BIG;
int cpuid_get(void *data, int n, __u32 *function, __u32 *index, __u32 *flags,
              __u32 *eax, __u32 *ebx, __u32 *ecx, __u32 *edx) {
  struct kvm_cpuid2 *cpuid = (struct kvm_cpuid2 *)data;
  if (n >= cpuid->nent) {
    return E2BIG;
  }
  *function = cpuid->entries[n].function;
  *index = cpuid->entries[n].index;
  *flags = cpuid->entries[n].flags;
  *eax = cpuid->entries[n].eax;
  *ebx = cpuid->entries[n].ebx;
  *ecx = cpuid->entries[n].ecx;
  *edx = cpuid->entries[n].edx;
  return 0;
}


x86 assembly (clang, -O0):
<cpuid_get>:
push   %rbp
mov    %rsp,%rbp
mov    0x20(%rbp),%rax
mov    0x18(%rbp),%rax
mov    0x10(%rbp),%rax
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %rdx,-0x20(%rbp)
mov    %rcx,-0x28(%rbp)
mov    %r8,-0x30(%rbp)
mov    %r9,-0x38(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x40(%rbp)
mov    -0x14(%rbp),%eax
mov    -0x40(%rbp),%rcx
cmp    (%rcx),%eax
jl     114f <cpuid_get+0x4f>
mov    0x2ea3(%rip),%rax
mov    (%rax),%eax
mov    %eax,-0x4(%rbp)
jmp    1219 <cpuid_get+0x119>
mov    -0x40(%rbp),%rax
mov    0x8(%rax),%rax
movslq -0x14(%rbp),%rcx
imul   $0x1c,%rcx,%rcx
add    %rcx,%rax
mov    0x18(%rax),%ecx
mov    -0x20(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x40(%rbp),%rax
mov    0x8(%rax),%rax
movslq -0x14(%rbp),%rcx
imul   $0x1c,%rcx,%rcx
add    %rcx,%rax
mov    0x14(%rax),%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x40(%rbp),%rax
mov    0x8(%rax),%rax
movslq -0x14(%rbp),%rcx
imul   $0x1c,%rcx,%rcx
add    %rcx,%rax
mov    0x10(%rax),%ecx
mov    -0x30(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x40(%rbp),%rax
mov    0x8(%rax),%rax
movslq -0x14(%rbp),%rcx
imul   $0x1c,%rcx,%rcx
add    %rcx,%rax
mov    0xc(%rax),%ecx
mov    -0x38(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x40(%rbp),%rax
mov    0x8(%rax),%rax
movslq -0x14(%rbp),%rcx
imul   $0x1c,%rcx,%rcx
add    %rcx,%rax
mov    0x8(%rax),%ecx
mov    0x10(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x40(%rbp),%rax
mov    0x8(%rax),%rax
movslq -0x14(%rbp),%rcx
imul   $0x1c,%rcx,%rcx
add    %rcx,%rax
mov    0x4(%rax),%ecx
mov    0x18(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x40(%rbp),%rax
mov    0x8(%rax),%rax
movslq -0x14(%rbp),%rcx
imul   $0x1c,%rcx,%rcx
add    %rcx,%rax
mov    (%rax),%ecx
mov    0x20(%rbp),%rax
mov    %ecx,(%rax)
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<cpuid_get>:
push   %rbx
cmp    %esi,(%rdi)
jle    1157 <cpuid_get+0x57>
mov    0x20(%rsp),%r10
mov    0x18(%rsp),%r11
mov    0x10(%rsp),%rax
mov    0x8(%rdi),%rdi
movslq %esi,%rsi
lea    (%rsi,%rsi,8),%rbx
lea    (%rbx,%rbx,2),%rbx
add    %rsi,%rbx
mov    0x18(%rdi,%rbx,1),%esi
mov    %esi,(%rdx)
mov    0x14(%rdi,%rbx,1),%edx
mov    %edx,(%rcx)
mov    0x10(%rdi,%rbx,1),%ecx
mov    %ecx,(%r8)
mov    0xc(%rdi,%rbx,1),%ecx
mov    %ecx,(%r9)
mov    0x8(%rdi,%rbx,1),%ecx
mov    %ecx,(%rax)
mov    0x4(%rdi,%rbx,1),%eax
mov    %eax,(%r11)
mov    (%rdi,%rbx,1),%eax
mov    %eax,(%r10)
xor    %eax,%eax
pop    %rbx
ret
mov    0x2e8a(%rip),%rax
mov    (%rax),%eax
pop    %rbx
ret

LLVM IR (-O0):
%struct.kvm_cpuid2 = type { i32, %struct.TYPE_2__* }
%struct.TYPE_2__ = type { i32, i32, i32, i32, i32, i32, i32 }
@E2BIG = global i32 0
define i32 @cpuid_get(i8* %0, i32 %1, i32* %2, i32* %3, i32* %4, i32* %5, i32* %6, i32* %7, i32* %8) {
%10 = alloca i32
%11 = alloca i8*
%12 = alloca i32
%13 = alloca i32*
%14 = alloca i32*
%15 = alloca i32*
%16 = alloca i32*
%17 = alloca i32*
%18 = alloca i32*
%19 = alloca i32*
%20 = alloca %struct.kvm_cpuid2*
store i8* %0, i8** %11
store i32 %1, i32* %12
store i32* %2, i32** %13
store i32* %3, i32** %14
store i32* %4, i32** %15
store i32* %5, i32** %16
store i32* %6, i32** %17
store i32* %7, i32** %18
store i32* %8, i32** %19
%21 = load i8*, i8** %11
%22 = bitcast i8* %21 to %struct.kvm_cpuid2*
store %struct.kvm_cpuid2* %22, %struct.kvm_cpuid2** %20
%23 = load i32, i32* %12
%24 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%25 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %24, i32 0, i32 0
%26 = load i32, i32* %25
%27 = icmp sge i32 %23, %26
br i1 %27, label %28, label %30
28: ; preds = %9
%29 = load i32, i32* @E2BIG
store i32 %29, i32* %10
br label %94
30: ; preds = %9
%31 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%32 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %31, i32 0, i32 1
%33 = load %struct.TYPE_2__*, %struct.TYPE_2__** %32
%34 = load i32, i32* %12
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %33, i64 %35
%37 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %36, i32 0, i32 6
%38 = load i32, i32* %37
%39 = load i32*, i32** %13
store i32 %38, i32* %39
%40 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%41 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %40, i32 0, i32 1
%42 = load %struct.TYPE_2__*, %struct.TYPE_2__** %41
%43 = load i32, i32* %12
%44 = sext i32 %43 to i64
%45 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %42, i64 %44
%46 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %45, i32 0, i32 5
%47 = load i32, i32* %46
%48 = load i32*, i32** %14
store i32 %47, i32* %48
%49 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%50 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %49, i32 0, i32 1
%51 = load %struct.TYPE_2__*, %struct.TYPE_2__** %50
%52 = load i32, i32* %12
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %51, i64 %53
%55 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %54, i32 0, i32 4
%56 = load i32, i32* %55
%57 = load i32*, i32** %15
store i32 %56, i32* %57
%58 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%59 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %58, i32 0, i32 1
%60 = load %struct.TYPE_2__*, %struct.TYPE_2__** %59
%61 = load i32, i32* %12
%62 = sext i32 %61 to i64
%63 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %60, i64 %62
%64 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %63, i32 0, i32 3
%65 = load i32, i32* %64
%66 = load i32*, i32** %16
store i32 %65, i32* %66
%67 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%68 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %67, i32 0, i32 1
%69 = load %struct.TYPE_2__*, %struct.TYPE_2__** %68
%70 = load i32, i32* %12
%71 = sext i32 %70 to i64
%72 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %69, i64 %71
%73 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %72, i32 0, i32 2
%74 = load i32, i32* %73
%75 = load i32*, i32** %17
store i32 %74, i32* %75
%76 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%77 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %76, i32 0, i32 1
%78 = load %struct.TYPE_2__*, %struct.TYPE_2__** %77
%79 = load i32, i32* %12
%80 = sext i32 %79 to i64
%81 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %78, i64 %80
%82 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %81, i32 0, i32 1
%83 = load i32, i32* %82
%84 = load i32*, i32** %18
store i32 %83, i32* %84
%85 = load %struct.kvm_cpuid2*, %struct.kvm_cpuid2** %20
%86 = getelementptr inbounds %struct.kvm_cpuid2, %struct.kvm_cpuid2* %85, i32 0, i32 1
%87 = load %struct.TYPE_2__*, %struct.TYPE_2__** %86
%88 = load i32, i32* %12
%89 = sext i32 %88 to i64
%90 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %87, i64 %89
%91 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %90, i32 0, i32 0
%92 = load i32, i32* %91
%93 = load i32*, i32** %19
store i32 %92, i32* %93
store i32 0, i32* %10
br label %94
94: ; preds = %30, %28
%95 = load i32, i32* %10
ret i32 %95
}

LLVM IR (-O2):
%struct.TYPE_2__ = type { i32, i32, i32, i32, i32, i32, i32 }
@E2BIG = global i32 0
define i32 @cpuid_get(i8* nocapture %0, i32 %1, i32* nocapture writeonly %2, i32* nocapture writeonly %3, i32* nocapture writeonly %4, i32* nocapture writeonly %5, i32* nocapture writeonly %6, i32* nocapture writeonly %7, i32* nocapture writeonly %8) {
%10 = bitcast i8* %0 to i32*
%11 = load i32, i32* %10
%12 = icmp sgt i32 %11, %1
br i1 %12, label %15, label %13
13: ; preds = %9
%14 = load i32, i32* @E2BIG
br label %34
15: ; preds = %9
%16 = getelementptr inbounds i8, i8* %0, i64 8
%17 = bitcast i8* %16 to %struct.TYPE_2__**
%18 = load %struct.TYPE_2__*, %struct.TYPE_2__** %17
%19 = sext i32 %1 to i64
%20 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %18, i64 %19, i32 6
%21 = load i32, i32* %20
store i32 %21, i32* %2
%22 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %18, i64 %19, i32 5
%23 = load i32, i32* %22
store i32 %23, i32* %3
%24 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %18, i64 %19, i32 4
%25 = load i32, i32* %24
store i32 %25, i32* %4
%26 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %18, i64 %19, i32 3
%27 = load i32, i32* %26
store i32 %27, i32* %5
%28 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %18, i64 %19, i32 2
%29 = load i32, i32* %28
store i32 %29, i32* %6
%30 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %18, i64 %19, i32 1
%31 = load i32, i32* %30
store i32 %31, i32* %7
%32 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %18, i64 %19, i32 0
%33 = load i32, i32* %32
store i32 %33, i32* %8
br label %34
34: ; preds = %15, %13
%35 = phi i32 [ %14, %13 ], [ 0, %15 ]
ret i32 %35
}