#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 */

/* Type definitions */
typedef int /*<<< orphan*/ uint8_t;
typedef size_t uint64_t;

/* Variables and functions */
int /*<<< orphan*/ assert(int);
int /*<<< orphan*/ memset(size_t *, int /*<<< orphan*/, int);
void ukvm_x86_setup_pagetables(uint8_t *mem, size_t mem_size) {
  uint64_t *pml4 = (uint64_t *)(mem + 0x2000);
  uint64_t *pdpte = (uint64_t *)(mem + 0x3000);
  uint64_t *pde = (uint64_t *)(mem + 0x4000);
  uint64_t paddr;
  assert((mem_size & (0x200000 - 1)) == 0);
  assert(mem_size <= (0x200000 * 512));
  memset(pml4, 0, 0x1000);
  memset(pdpte, 0, 0x1000);
  memset(pde, 0, 0x1000);
  *pml4 = 0x3000 | (((1UL) << (0)) | ((1UL) << (1)));
  *pdpte = 0x4000 | (((1UL) << (0)) | ((1UL) << (1)));
  for (paddr = 0; paddr < mem_size; paddr += 0x200000, pde++)
    *pde = paddr | (((1UL) << (0)) | ((1UL) << (1)) | ((1UL) << (7)));
}


x86 assembly (clang, -O0):
<ukvm_x86_setup_pagetables>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rax
add    $0x8000,%rax
mov    %rax,-0x18(%rbp)
mov    -0x8(%rbp),%rax
add    $0xc000,%rax
mov    %rax,-0x20(%rbp)
mov    -0x8(%rbp),%rax
add    $0x10000,%rax
mov    %rax,-0x28(%rbp)
mov    -0x10(%rbp),%rax
and    $0x1fffff,%rax
cmp    $0x0,%rax
sete   %al
and    $0x1,%al
movzbl %al,%edi
call   1040 <assert@plt>
cmpq   $0x40000000,-0x10(%rbp)
40
setbe  %al
and    $0x1,%al
movzbl %al,%edi
call   1040 <assert@plt>
mov    -0x18(%rbp),%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1030 <memset@plt>
mov    -0x20(%rbp),%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1030 <memset@plt>
mov    -0x28(%rbp),%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1030 <memset@plt>
mov    -0x18(%rbp),%rax
movq   $0x3003,(%rax)
mov    -0x20(%rbp),%rax
movq   $0x4003,(%rax)
movq   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%rax
cmp    -0x10(%rbp),%rax
jae    1217 <ukvm_x86_setup_pagetables+0xf7>
mov    -0x30(%rbp),%rcx
or     $0x83,%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x30(%rbp),%rax
add    $0x200000,%rax
mov    %rax,-0x30(%rbp)
mov    -0x28(%rbp),%rax
add    $0x8,%rax
mov    %rax,-0x28(%rbp)
jmp    11d8 <ukvm_x86_setup_pagetables+0xb8>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<ukvm_x86_setup_pagetables>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %rsi,%r14
mov    %rdi,%r15
lea    0x8000(%rdi),%r12
lea    0xc000(%rdi),%r13
lea    0x10000(%rdi),%rbx
xor    %edi,%edi
test   $0x1fffff,%r14d
sete   %dil
call   1040 <assert@plt>
xor    %edi,%edi
cmp    $0x40000001,%r14
setb   %dil
call   1040 <assert@plt>
mov    %r12,%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1030 <memset@plt>
mov    %r13,%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1030 <memset@plt>
mov    %rbx,%rdi
xor    %esi,%esi
mov    $0x1000,%edx
call   1030 <memset@plt>
movq   $0x3003,0x8000(%r15)
movq   $0x4003,0xc000(%r15)
test   %r14,%r14
je     12e9 <ukvm_x86_setup_pagetables+0x1c9>
lea    -0x1(%r14),%rcx
cmp    $0x600000,%rcx
jae    11c8 <ukvm_x86_setup_pagetables+0xa8>
xor    %eax,%eax
jmp    12d0 <ukvm_x86_setup_pagetables+0x1b0>
shr    $0x15,%rcx
add    $0x1,%rcx
mov    %rcx,%rax
and    $0xfffffffffffffffc,%rax
lea    -0x4(%rax),%rdx
mov    %rdx,%rsi
shr    $0x2,%rsi
add    $0x1,%rsi
test   %rdx,%rdx
je     12f3 <ukvm_x86_setup_pagetables+0x1d3>
mov    %rsi,%rdi
and    $0xfffffffffffffffe,%rdi
movdqa 0xe02(%rip),%xmm0
xor    %edx,%edx
movdqa 0xe08(%rip),%xmm1
movdqa 0xe10(%rip),%xmm2
movdqa 0xe18(%rip),%xmm3
movdqa 0xe20(%rip),%xmm4
movdqa 0xe28(%rip),%xmm5
nopl   0x0(%rax,%rax,1)
movdqa %xmm0,%xmm6
paddq  %xmm1,%xmm6
movdqa %xmm0,%xmm7
por    %xmm2,%xmm7
por    %xmm2,%xmm6
movdqu %xmm7,0x10000(%r15,%rdx,8)
movdqu %xmm6,0x10010(%r15,%rdx,8)
movdqa %xmm0,%xmm6
paddq  %xmm3,%xmm6
movdqa %xmm0,%xmm7
paddq  %xmm4,%xmm7
por    %xmm2,%xmm6
por    %xmm2,%xmm7
movdqu %xmm6,0x10020(%r15,%rdx,8)
movdqu %xmm7,0x10030(%r15,%rdx,8)
add    $0x8,%rdx
paddq  %xmm5,%xmm0
add    $0xfffffffffffffffe,%rdi
jne    1230 <ukvm_x86_setup_pagetables+0x110>
test   $0x1,%sil
je     12bf <ukvm_x86_setup_pagetables+0x19f>
movdqa 0xd70(%rip),%xmm1
paddq  %xmm0,%xmm1
movdqa 0xd74(%rip),%xmm2
por    %xmm2,%xmm0
por    %xmm2,%xmm1
movdqu %xmm0,(%rbx,%rdx,8)
movdqu %xmm1,0x10(%rbx,%rdx,8)
cmp    %rax,%rcx
je     12e9 <ukvm_x86_setup_pagetables+0x1c9>
lea    (%rbx,%rax,8),%rbx
shl    $0x15,%rax
nopl   0x0(%rax)
lea    0x83(%rax),%rcx
mov    %rcx,(%rbx)
add    $0x200000,%rax
add    $0x8,%rbx
cmp    %r14,%rax
jb     12d0 <ukvm_x86_setup_pagetables+0x1b0>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret
movdqa 0xd05(%rip),%xmm0
xor    %edx,%edx
test   $0x1,%sil
jne    1298 <ukvm_x86_setup_pagetables+0x178>
jmp    12bf <ukvm_x86_setup_pagetables+0x19f>

LLVM IR (-O0):
define void @ukvm_x86_setup_pagetables(i32* %0, i64 %1) {
%3 = alloca i32*
%4 = alloca i64
%5 = alloca i64*
%6 = alloca i64*
%7 = alloca i64*
%8 = alloca i64
store i32* %0, i32** %3
store i64 %1, i64* %4
%9 = load i32*, i32** %3
%10 = getelementptr inbounds i32, i32* %9, i64 8192
%11 = bitcast i32* %10 to i64*
store i64* %11, i64** %5
%12 = load i32*, i32** %3
%13 = getelementptr inbounds i32, i32* %12, i64 12288
%14 = bitcast i32* %13 to i64*
store i64* %14, i64** %6
%15 = load i32*, i32** %3
%16 = getelementptr inbounds i32, i32* %15, i64 16384
%17 = bitcast i32* %16 to i64*
store i64* %17, i64** %7
%18 = load i64, i64* %4
%19 = and i64 %18, 2097151
%20 = icmp eq i64 %19, 0
%21 = zext i1 %20 to i32
%22 = call i32 @assert(i32 %21)
%23 = load i64, i64* %4
%24 = icmp ule i64 %23, 1073741824
%25 = zext i1 %24 to i32
%26 = call i32 @assert(i32 %25)
%27 = load i64*, i64** %5
%28 = call i32 @memset(i64* %27, i32 0, i32 4096)
%29 = load i64*, i64** %6
%30 = call i32 @memset(i64* %29, i32 0, i32 4096)
%31 = load i64*, i64** %7
%32 = call i32 @memset(i64* %31, i32 0, i32 4096)
%33 = load i64*, i64** %5
store i64 12291, i64* %33
%34 = load i64*, i64** %6
store i64 16387, i64* %34
store i64 0, i64* %8
br label %35
35: ; preds = %43, %2
%36 = load i64, i64* %8
%37 = load i64, i64* %4
%38 = icmp ult i64 %36, %37
br i1 %38, label %39, label %48
39: ; preds = %35
%40 = load i64, i64* %8
%41 = or i64 %40, 131
%42 = load i64*, i64** %7
store i64 %41, i64* %42
br label %43
43: ; preds = %39
%44 = load i64, i64* %8
%45 = add i64 %44, 2097152
store i64 %45, i64* %8
%46 = load i64*, i64** %7
%47 = getelementptr inbounds i64, i64* %46, i32 1
store i64* %47, i64** %7
br label %35
48: ; preds = %35
ret void
}

LLVM IR (-O2):
define void @ukvm_x86_setup_pagetables(i32* %0, i64 %1) {
%3 = getelementptr inbounds i32, i32* %0, i64 8192
%4 = bitcast i32* %3 to i64*
%5 = getelementptr inbounds i32, i32* %0, i64 12288
%6 = bitcast i32* %5 to i64*
%7 = getelementptr inbounds i32, i32* %0, i64 16384
%8 = bitcast i32* %7 to i64*
%9 = and i64 %1, 2097151
%10 = icmp eq i64 %9, 0
%11 = zext i1 %10 to i32
%12 = tail call i32 @assert(i32 %11)
%13 = icmp ult i64 %1, 1073741825
%14 = zext i1 %13 to i32
%15 = tail call i32 @assert(i32 %14)
%16 = tail call i32 @memset(i64* %4, i32 0, i32 4096)
%17 = tail call i32 @memset(i64* %6, i32 0, i32 4096)
%18 = tail call i32 @memset(i64* %8, i32 0, i32 4096)
store i64 12291, i64* %4
store i64 16387, i64* %6
%19 = icmp eq i64 %1, 0
br i1 %19, label %84, label %20
20: ; preds = %2
%21 = add i64 %1, -1
%22 = lshr i64 %21, 21
%23 = add nuw nsw i64 %22, 1
%24 = icmp ult i64 %21, 6291456
br i1 %24, label %74, label %25
25: ; preds = %20
%26 = and i64 %23, 17592186044412
%27 = shl i64 %26, 21
%28 = getelementptr i64, i64* %8, i64 %26
%29 = add nsw i64 %26, -4
%30 = lshr exact i64 %29, 2
%31 = add nuw nsw i64 %30, 1
%32 = and i64 %31, 1
%33 = icmp eq i64 %29, 0
br i1 %33, label %60, label %34
34: ; preds = %25
%35 = and i64 %31, 9223372036854775806
br label %36
36: ; preds = %36, %34
%37 = phi i64 [ 0, %34 ], [ %56, %36 ]
%38 = phi <2 x i64> [ <i64 0, i64 2097152>, %34 ], [ %57, %36 ]
%39 = phi i64 [ 0, %34 ], [ %58, %36 ]
%40 = add <2 x i64> %38, <i64 4194304, i64 4194304>
%41 = getelementptr i64, i64* %8, i64 %37
%42 = or <2 x i64> %38, <i64 131, i64 131>
%43 = or <2 x i64> %40, <i64 131, i64 131>
%44 = bitcast i64* %41 to <2 x i64>*
store <2 x i64> %42, <2 x i64>* %44
%45 = getelementptr i64, i64* %41, i64 2
%46 = bitcast i64* %45 to <2 x i64>*
store <2 x i64> %43, <2 x i64>* %46
%47 = or i64 %37, 4
%48 = add <2 x i64> %38, <i64 8388608, i64 8388608>
%49 = add <2 x i64> %38, <i64 12582912, i64 12582912>
%50 = getelementptr i64, i64* %8, i64 %47
%51 = or <2 x i64> %48, <i64 131, i64 131>
%52 = or <2 x i64> %49, <i64 131, i64 131>
%53 = bitcast i64* %50 to <2 x i64>*
store <2 x i64> %51, <2 x i64>* %53
%54 = getelementptr i64, i64* %50, i64 2
%55 = bitcast i64* %54 to <2 x i64>*
store <2 x i64> %52, <2 x i64>* %55
%56 = add nuw i64 %37, 8
%57 = add <2 x i64> %38, <i64 16777216, i64 16777216>
%58 = add i64 %39, 2
%59 = icmp eq i64 %58, %35
br i1 %59, label %60, label %36
60: ; preds = %36, %25
%61 = phi i64 [ 0, %25 ], [ %56, %36 ]
%62 = phi <2 x i64> [ <i64 0, i64 2097152>, %25 ], [ %57, %36 ]
%63 = icmp eq i64 %32, 0
br i1 %63, label %72, label %64
64: ; preds = %60
%65 = add <2 x i64> %62, <i64 4194304, i64 4194304>
%66 = getelementptr i64, i64* %8, i64 %61
%67 = or <2 x i64> %62, <i64 131, i64 131>
%68 = or <2 x i64> %65, <i64 131, i64 131>
%69 = bitcast i64* %66 to <2 x i64>*
store <2 x i64> %67, <2 x i64>* %69
%70 = getelementptr i64, i64* %66, i64 2
%71 = bitcast i64* %70 to <2 x i64>*
store <2 x i64> %68, <2 x i64>* %71
br label %72
72: ; preds = %60, %64
%73 = icmp eq i64 %23, %26
br i1 %73, label %84, label %74
74: ; preds = %20, %72
%75 = phi i64 [ 0, %20 ], [ %27, %72 ]
%76 = phi i64* [ %8, %20 ], [ %28, %72 ]
br label %77
77: ; preds = %74, %77
%78 = phi i64 [ %81, %77 ], [ %75, %74 ]
%79 = phi i64* [ %82, %77 ], [ %76, %74 ]
%80 = or i64 %78, 131
store i64 %80, i64* %79
%81 = add nuw i64 %78, 2097152
%82 = getelementptr inbounds i64, i64* %79, i64 1
%83 = icmp ult i64 %81, %1
br i1 %83, label %77, label %84
84: ; preds = %77, %72, %2
ret void
}