long handle_brand_string(const int *name, int nlen, void *old,
                         unsigned long *oldlen, void *_new,
                         unsigned long newlen) {
  unsigned int level = 0;
  unsigned int eax = 0;
  union {
    struct {
      unsigned int ebx;
      unsigned int edx;
      unsigned int ecx;
    };
    char name[13];
  } v;
  __asm__("cpuid\n\t"
          : "=a"(eax), "=b"(v.ebx), "=c"(v.ecx), "=d"(v.edx)
          : "0"(level));
  v.name[12] = 0;
  copyout_string(v.name, (char *)old, oldlen);
  return 0;
}


x86 assembly (clang, -O0):
<handle_brand_string>:
push   %rbp
mov    %rsp,%rbp
push   %rbx
sub    $0x48,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %rdx,-0x20(%rbp)
mov    %rcx,-0x28(%rbp)
mov    %r8,-0x30(%rbp)
mov    %r9,-0x38(%rbp)
movl   $0x0,-0x3c(%rbp)
movl   $0x0,-0x40(%rbp)
mov    -0x3c(%rbp),%eax
cpuid
mov    %eax,-0x40(%rbp)
mov    %ebx,-0x50(%rbp)
mov    %ecx,-0x48(%rbp)
mov    %edx,-0x4c(%rbp)
movb   $0x0,-0x44(%rbp)
lea    -0x50(%rbp),%rdi
mov    -0x20(%rbp),%rsi
mov    -0x28(%rbp),%rdx
mov    $0x0,%al
call   1030 <copyout_string@plt>
xor    %eax,%eax
add    $0x48,%rsp
pop    %rbx
pop    %rbp
ret

x86 assembly (clang, -O2):
<handle_brand_string>:
push   %rbx
sub    $0x10,%rsp
mov    %rcx,%r8
mov    %rdx,%rsi
xor    %eax,%eax
cpuid
mov    %ebx,(%rsp)
mov    %ecx,0x8(%rsp)
mov    %edx,0x4(%rsp)
movb   $0x0,0xc(%rsp)
mov    %rsp,%rdi
mov    %r8,%rdx
xor    %eax,%eax
call   1030 <copyout_string@plt>
xor    %eax,%eax
add    $0x10,%rsp
pop    %rbx
ret

LLVM IR (-O0):
%union.anon = type { %struct.anon, [4 x i8] }
%struct.anon = type { i32, i32, i32 }
define i64 @handle_brand_string(i32* %0, i32 %1, i8* %2, i64* %3, i8* %4, i64 %5) {
%7 = alloca i32*
%8 = alloca i32
%9 = alloca i8*
%10 = alloca i64*
%11 = alloca i8*
%12 = alloca i64
%13 = alloca i32
%14 = alloca i32
%15 = alloca %union.anon
store i32* %0, i32** %7
store i32 %1, i32* %8
store i8* %2, i8** %9
store i64* %3, i64** %10
store i8* %4, i8** %11
store i64 %5, i64* %12
store i32 0, i32* %13
store i32 0, i32* %14
%16 = bitcast %union.anon* %15 to %struct.anon*
%17 = getelementptr inbounds %struct.anon, %struct.anon* %16, i32 0, i32 0
%18 = bitcast %union.anon* %15 to %struct.anon*
%19 = getelementptr inbounds %struct.anon, %struct.anon* %18, i32 0, i32 2
%20 = bitcast %union.anon* %15 to %struct.anon*
%21 = getelementptr inbounds %struct.anon, %struct.anon* %20, i32 0, i32 1
%22 = load i32, i32* %13
%23 = call { i32, i32, i32, i32 } asm "cpuid\0A\09", "={ax},={bx},={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 %22)
%24 = extractvalue { i32, i32, i32, i32 } %23, 0
%25 = extractvalue { i32, i32, i32, i32 } %23, 1
%26 = extractvalue { i32, i32, i32, i32 } %23, 2
%27 = extractvalue { i32, i32, i32, i32 } %23, 3
store i32 %24, i32* %14
store i32 %25, i32* %17
store i32 %26, i32* %19
store i32 %27, i32* %21
%28 = bitcast %union.anon* %15 to [13 x i8]*
%29 = getelementptr inbounds [13 x i8], [13 x i8]* %28, i64 0, i64 12
store i8 0, i8* %29
%30 = bitcast %union.anon* %15 to [13 x i8]*
%31 = getelementptr inbounds [13 x i8], [13 x i8]* %30, i64 0, i64 0
%32 = load i8*, i8** %9
%33 = load i64*, i64** %10
%34 = call i32 (i8*, i8*, i64*, ...) bitcast (i32 (...)* @copyout_string to i32 (i8*, i8*, i64*, ...)*)(i8* %31, i8* %32, i64* %33)
ret i64 0
}

LLVM IR (-O2):
%union.anon = type { %struct.anon, [4 x i8] }
%struct.anon = type { i32, i32, i32 }
define i64 @handle_brand_string(i32* nocapture readnone %0, i32 %1, i8* %2, i64* %3, i8* nocapture readnone %4, i64 %5) {
%7 = alloca %union.anon
%8 = bitcast %union.anon* %7 to i8*
%9 = getelementptr inbounds %union.anon, %union.anon* %7, i64 0, i32 0, i32 0
%10 = getelementptr inbounds %union.anon, %union.anon* %7, i64 0, i32 0, i32 2
%11 = getelementptr inbounds %union.anon, %union.anon* %7, i64 0, i32 0, i32 1
%12 = tail call { i32, i32, i32, i32 } asm "cpuid\0A\09", "={ax},={bx},={cx},={dx},0,~{dirflag},~{fpsr},~{flags}"(i32 0)
%13 = extractvalue { i32, i32, i32, i32 } %12, 1
%14 = extractvalue { i32, i32, i32, i32 } %12, 2
%15 = extractvalue { i32, i32, i32, i32 } %12, 3
store i32 %13, i32* %9
store i32 %14, i32* %10
store i32 %15, i32* %11
%16 = getelementptr inbounds %union.anon, %union.anon* %7, i64 0, i32 1, i64 0
store i8 0, i8* %16
%17 = call i32 (i8*, i8*, i64*, ...) bitcast (i32 (...)* @copyout_string to i32 (i8*, i8*, i64*, ...)*)(i8* %8, i8* %2, i64* %3)
ret i64 0
}