void load_kernel(void) {
  void *setup_addr;
  void *initrd_addr;
  void *kernel_addr;
  void *cmdline_addr;
  unsigned int setup_size;
  unsigned int initrd_size;
  unsigned int kernel_size;
  unsigned int cmdline_size;
  unsigned int initrd_end_page, max_allowed_page;
  unsigned int segment_addr, stack_addr;
  bios_cfg_read_entry(&setup_addr, 0x16, 4);
  bios_cfg_read_entry(&setup_size, 0x17, 4);
  bios_cfg_read_entry(setup_addr, 0x18, setup_size);
  set_es(setup_addr);
  if (readw_es(0x206) < 0x203) {
    writel_es(0x22c, 0x37ffffff);
  }
  bios_cfg_read_entry(&initrd_addr, 0x0a, 4);
  bios_cfg_read_entry(&initrd_size, 0x0b, 4);
  initrd_end_page = ((unsigned int)(initrd_addr + initrd_size) & -4096);
  max_allowed_page = (readl_es(0x22c) & -4096);
  if (initrd_end_page != 0 && max_allowed_page != 0 &&
      initrd_end_page != max_allowed_page) {
    initrd_addr = (void *)((get_e801_addr() - initrd_size) & -4096);
    writel_es(0x218, (unsigned int)initrd_addr);
  }
  bios_cfg_read_entry(initrd_addr, 0x12, initrd_size);
  bios_cfg_read_entry(&kernel_addr, 0x07, 4);
  bios_cfg_read_entry(&kernel_size, 0x08, 4);
  bios_cfg_read_entry(kernel_addr, 0x11, kernel_size);
  bios_cfg_read_entry(&cmdline_addr, 0x13, 4);
  bios_cfg_read_entry(&cmdline_size, 0x14, 4);
  bios_cfg_read_entry(cmdline_addr, 0x15, cmdline_size);
  segment_addr = ((unsigned int)setup_addr >> 4);
  stack_addr = (unsigned int)(cmdline_addr - setup_addr - 16);
  asm("movw %%ax, %%ds\n"
      "movw %%ax, %%es\n"
      "movw %%ax, %%fs\n"
      "movw %%ax, %%gs\n"
      "movw %%ax, %%ss\n"
      "movl %%ebx, %%esp\n"
      "addw $0x20, %%ax\n"
      "pushw %%ax\n"
      "pushw $0\n"
      "xor %%ebx, %%ebx\n"
      "xor %%ecx, %%ecx\n"
      "xor %%edx, %%edx\n"
      "xor %%edi, %%edi\n"
      "xor %%ebp, %%ebp\n"
      "lretw\n"
      :
      : "a"(segment_addr), "b"(stack_addr));
}


x86 assembly (clang, -O0):
<load_kernel>:
push   %rbp
mov    %rsp,%rbp
push   %rbx
sub    $0x48,%rsp
lea    -0x10(%rbp),%rdi
mov    $0x16,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
lea    -0x2c(%rbp),%rdi
mov    $0x17,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
mov    -0x10(%rbp),%rdi
mov    -0x2c(%rbp),%edx
mov    $0x18,%esi
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
mov    -0x10(%rbp),%rdi
mov    $0x0,%al
call   1080 <set_es@plt>
mov    $0x206,%edi
mov    $0x0,%al
call   1030 <readw_es@plt>
cmp    $0x203,%eax
jge    11d9 <load_kernel+0x79>
mov    $0x22c,%edi
mov    $0x37ffffff,%esi
mov    $0x0,%al
call   1060 <writel_es@plt>
lea    -0x18(%rbp),%rdi
mov    $0xa,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
lea    -0x30(%rbp),%rdi
mov    $0xb,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
mov    -0x18(%rbp),%rax
mov    -0x30(%rbp),%ecx
add    %rcx,%rax
and    $0xfffff000,%eax
mov    %eax,-0x3c(%rbp)
mov    $0x22c,%edi
mov    $0x0,%al
call   1070 <readl_es@plt>
and    $0xfffff000,%eax
mov    %eax,-0x40(%rbp)
cmpl   $0x0,-0x3c(%rbp)
je     1270 <load_kernel+0x110>
cmpl   $0x0,-0x40(%rbp)
je     1270 <load_kernel+0x110>
mov    -0x3c(%rbp),%eax
cmp    -0x40(%rbp),%eax
je     1270 <load_kernel+0x110>
mov    $0x0,%al
call   1050 <get_e801_addr@plt>
sub    -0x30(%rbp),%eax
and    $0xfffff000,%eax
mov    %eax,%eax
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rax
mov    %eax,%esi
mov    $0x218,%edi
mov    $0x0,%al
call   1060 <writel_es@plt>
mov    -0x18(%rbp),%rdi
mov    -0x30(%rbp),%edx
mov    $0x12,%esi
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
lea    -0x20(%rbp),%rdi
mov    $0x7,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
lea    -0x34(%rbp),%rdi
mov    $0x8,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
mov    -0x20(%rbp),%rdi
mov    -0x34(%rbp),%edx
mov    $0x11,%esi
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
lea    -0x28(%rbp),%rdi
mov    $0x13,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
lea    -0x38(%rbp),%rdi
mov    $0x14,%esi
mov    $0x4,%edx
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
mov    -0x28(%rbp),%rdi
mov    -0x38(%rbp),%edx
mov    $0x15,%esi
mov    $0x0,%al
call   1040 <bios_cfg_read_entry@plt>
mov    -0x10(%rbp),%rax
shr    $0x4,%eax
mov    %eax,-0x44(%rbp)
mov    -0x28(%rbp),%rax
mov    -0x10(%rbp),%rcx
sub    %rcx,%rax
sub    $0x10,%rax
mov    %eax,-0x48(%rbp)
mov    -0x44(%rbp),%eax
mov    -0x48(%rbp),%ebx
mov    %eax,%ds
mov    %eax,%es
mov    %eax,%fs
mov    %eax,%gs
mov    %eax,%ss
mov    %ebx,%esp
add    $0x20,%ax
push   %ax
pushw  $0x0
xor    %ebx,%ebx
xor    %ecx,%ecx
xor    %edx,%edx
xor    %edi,%edi
xor    %ebp,%ebp
lretw
add    $0x48,%rsp
pop    %rbx
pop    %rbp
ret

x86 assembly (clang, -O2):
<load_kernel>:
push   %rbx
sub    $0x40,%rsp
lea    0x18(%rsp),%rdi
mov    $0x16,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
lea    0x2c(%rsp),%rdi
mov    $0x17,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
mov    0x18(%rsp),%rdi
mov    0x2c(%rsp),%edx
mov    $0x18,%esi
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
mov    0x18(%rsp),%rdi
xor    %eax,%eax
call   1080 <set_es@plt>
mov    $0x206,%edi
xor    %eax,%eax
call   1030 <readw_es@plt>
cmp    $0x202,%eax
jg     11d6 <load_kernel+0x76>
mov    $0x22c,%edi
mov    $0x37ffffff,%esi
xor    %eax,%eax
call   1060 <writel_es@plt>
lea    0x10(%rsp),%rdi
mov    $0xa,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
lea    0xc(%rsp),%rdi
mov    $0xb,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
mov    0x10(%rsp),%ebx
add    0xc(%rsp),%ebx
mov    $0x22c,%edi
xor    %eax,%eax
call   1070 <readl_es@plt>
and    $0xfffff000,%ebx
je     124c <load_kernel+0xec>
and    $0xfffff000,%eax
je     124c <load_kernel+0xec>
cmp    %eax,%ebx
je     124c <load_kernel+0xec>
xor    %eax,%eax
call   1050 <get_e801_addr@plt>
sub    0xc(%rsp),%eax
and    $0xfffff000,%eax
mov    %rax,0x10(%rsp)
mov    $0x218,%edi
mov    %eax,%esi
xor    %eax,%eax
call   1060 <writel_es@plt>
mov    0x10(%rsp),%rdi
mov    0xc(%rsp),%edx
mov    $0x12,%esi
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
lea    0x38(%rsp),%rdi
mov    $0x7,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
lea    0x28(%rsp),%rdi
mov    $0x8,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
mov    0x38(%rsp),%rdi
mov    0x28(%rsp),%edx
mov    $0x11,%esi
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
lea    0x30(%rsp),%rdi
mov    $0x13,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
lea    0x24(%rsp),%rdi
mov    $0x14,%esi
mov    $0x4,%edx
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
mov    0x30(%rsp),%rdi
mov    0x24(%rsp),%edx
mov    $0x15,%esi
xor    %eax,%eax
call   1040 <bios_cfg_read_entry@plt>
mov    0x18(%rsp),%eax
mov    0x30(%rsp),%ebx
sub    %eax,%ebx
shr    $0x4,%eax
add    $0xfffffff0,%ebx
mov    %eax,%ds
mov    %eax,%es
mov    %eax,%fs
mov    %eax,%gs
mov    %eax,%ss
mov    %ebx,%esp
add    $0x20,%ax
push   %ax
pushw  $0x0
xor    %ebx,%ebx
xor    %ecx,%ecx
xor    %edx,%edx
xor    %edi,%edi
xor    %ebp,%ebp
lretw
add    $0x40,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define void @load_kernel() {
%1 = alloca i8*
%2 = alloca i8*
%3 = alloca i8*
%4 = alloca i8*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %1, i32 22, i32 4)
%14 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %5, i32 23, i32 4)
%15 = load i8*, i8** %1
%16 = load i32, i32* %5
%17 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %15, i32 24, i32 %16)
%18 = load i8*, i8** %1
%19 = call i32 (i8*, ...) bitcast (i32 (...)* @set_es to i32 (i8*, ...)*)(i8* %18)
%20 = call i32 (i32, ...) bitcast (i32 (...)* @readw_es to i32 (i32, ...)*)(i32 518)
%21 = icmp slt i32 %20, 515
br i1 %21, label %22, label %24
22: ; preds = %0
%23 = call i32 (i32, i32, ...) bitcast (i32 (...)* @writel_es to i32 (i32, i32, ...)*)(i32 556, i32 939524095)
br label %24
24: ; preds = %22, %0
%25 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %2, i32 10, i32 4)
%26 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %6, i32 11, i32 4)
%27 = load i8*, i8** %2
%28 = load i32, i32* %6
%29 = zext i32 %28 to i64
%30 = getelementptr i8, i8* %27, i64 %29
%31 = ptrtoint i8* %30 to i32
%32 = and i32 %31, -4096
store i32 %32, i32* %9
%33 = call i32 (i32, ...) bitcast (i32 (...)* @readl_es to i32 (i32, ...)*)(i32 556)
%34 = and i32 %33, -4096
store i32 %34, i32* %10
%35 = load i32, i32* %9
%36 = icmp ne i32 %35, 0
br i1 %36, label %37, label %54
37: ; preds = %24
%38 = load i32, i32* %10
%39 = icmp ne i32 %38, 0
br i1 %39, label %40, label %54
40: ; preds = %37
%41 = load i32, i32* %9
%42 = load i32, i32* %10
%43 = icmp ne i32 %41, %42
br i1 %43, label %44, label %54
44: ; preds = %40
%45 = call i32 (...) @get_e801_addr()
%46 = load i32, i32* %6
%47 = sub i32 %45, %46
%48 = and i32 %47, -4096
%49 = zext i32 %48 to i64
%50 = inttoptr i64 %49 to i8*
store i8* %50, i8** %2
%51 = load i8*, i8** %2
%52 = ptrtoint i8* %51 to i32
%53 = call i32 (i32, i32, ...) bitcast (i32 (...)* @writel_es to i32 (i32, i32, ...)*)(i32 536, i32 %52)
br label %54
54: ; preds = %44, %40, %37, %24
%55 = load i8*, i8** %2
%56 = load i32, i32* %6
%57 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %55, i32 18, i32 %56)
%58 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %3, i32 7, i32 4)
%59 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %7, i32 8, i32 4)
%60 = load i8*, i8** %3
%61 = load i32, i32* %7
%62 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %60, i32 17, i32 %61)
%63 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %4, i32 19, i32 4)
%64 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %8, i32 20, i32 4)
%65 = load i8*, i8** %4
%66 = load i32, i32* %8
%67 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %65, i32 21, i32 %66)
%68 = load i8*, i8** %1
%69 = ptrtoint i8* %68 to i32
%70 = lshr i32 %69, 4
store i32 %70, i32* %11
%71 = load i8*, i8** %4
%72 = load i8*, i8** %1
%73 = ptrtoint i8* %71 to i64
%74 = ptrtoint i8* %72 to i64
%75 = sub i64 %73, %74
%76 = sub nsw i64 %75, 16
%77 = trunc i64 %76 to i32
store i32 %77, i32* %12
%78 = load i32, i32* %11
%79 = load i32, i32* %12
ret void
}

LLVM IR (-O2):
define void @load_kernel() {
%1 = alloca i8*
%2 = alloca i8*
%3 = alloca i8*
%4 = alloca i8*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = bitcast i8** %1 to i8*
%10 = bitcast i8** %2 to i8*
%11 = bitcast i8** %3 to i8*
%12 = bitcast i8** %4 to i8*
%13 = bitcast i32* %5 to i8*
%14 = bitcast i32* %6 to i8*
%15 = bitcast i32* %7 to i8*
%16 = bitcast i32* %8 to i8*
%17 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %1, i32 22, i32 4)
%18 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %5, i32 23, i32 4)
%19 = load i8*, i8** %1
%20 = load i32, i32* %5
%21 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %19, i32 24, i32 %20)
%22 = load i8*, i8** %1
%23 = call i32 (i8*, ...) bitcast (i32 (...)* @set_es to i32 (i8*, ...)*)(i8* %22)
%24 = call i32 (i32, ...) bitcast (i32 (...)* @readw_es to i32 (i32, ...)*)(i32 518)
%25 = icmp slt i32 %24, 515
br i1 %25, label %26, label %28
26: ; preds = %0
%27 = call i32 (i32, i32, ...) bitcast (i32 (...)* @writel_es to i32 (i32, i32, ...)*)(i32 556, i32 939524095)
br label %28
28: ; preds = %26, %0
%29 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %2, i32 10, i32 4)
%30 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %6, i32 11, i32 4)
%31 = load i8*, i8** %2
%32 = load i32, i32* %6
%33 = zext i32 %32 to i64
%34 = getelementptr i8, i8* %31, i64 %33
%35 = ptrtoint i8* %34 to i64
%36 = trunc i64 %35 to i32
%37 = and i32 %36, -4096
%38 = call i32 (i32, ...) bitcast (i32 (...)* @readl_es to i32 (i32, ...)*)(i32 556)
%39 = and i32 %38, -4096
%40 = icmp eq i32 %37, 0
%41 = icmp eq i32 %39, 0
%42 = select i1 %40, i1 true, i1 %41
%43 = icmp eq i32 %37, %39
%44 = select i1 %42, i1 true, i1 %43
br i1 %44, label %53, label %45
45: ; preds = %28
%46 = call i32 (...) @get_e801_addr()
%47 = load i32, i32* %6
%48 = sub i32 %46, %47
%49 = and i32 %48, -4096
%50 = zext i32 %49 to i64
%51 = inttoptr i64 %50 to i8*
store i8* %51, i8** %2
%52 = call i32 (i32, i32, ...) bitcast (i32 (...)* @writel_es to i32 (i32, i32, ...)*)(i32 536, i32 %49)
br label %53
53: ; preds = %45, %28
%54 = load i8*, i8** %2
%55 = load i32, i32* %6
%56 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %54, i32 18, i32 %55)
%57 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %3, i32 7, i32 4)
%58 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %7, i32 8, i32 4)
%59 = load i8*, i8** %3
%60 = load i32, i32* %7
%61 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %59, i32 17, i32 %60)
%62 = call i32 (i8**, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8**, i32, i32, ...)*)(i8** %4, i32 19, i32 4)
%63 = call i32 (i32*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i32*, i32, i32, ...)*)(i32* %8, i32 20, i32 4)
%64 = load i8*, i8** %4
%65 = load i32, i32* %8
%66 = call i32 (i8*, i32, i32, ...) bitcast (i32 (...)* @bios_cfg_read_entry to i32 (i8*, i32, i32, ...)*)(i8* %64, i32 21, i32 %65)
%67 = load i8*, i8** %1
%68 = ptrtoint i8* %67 to i64
%69 = trunc i64 %68 to i32
%70 = lshr i32 %69, 4
%71 = load i8*, i8** %4
%72 = ptrtoint i8* %71 to i64
%73 = sub i64 %72, %68
%74 = trunc i64 %73 to i32
%75 = add i32 %74, -16
ret void
}