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

/* Variables and functions */
int /*<<< orphan*/ printf(char *, unsigned int, unsigned int);
unsigned vtopPageProperty(char *mem, unsigned size, unsigned pgd, unsigned addr,
                          int *rw, int *us, int *g, int *ps) {
  unsigned pde_addr = (pgd & ~0xfff) + ((addr >> 20) & ~3);
  if (pde_addr > size) {
    printf("ERROR 1 addr %x pde %x\n", addr, pde_addr);
    return -1;
  }
  unsigned pde = *(unsigned *)((unsigned)mem + pde_addr);
  unsigned pte;
  unsigned pte_addr;
  unsigned page_size;
  if (!(pde & (1 << 0))) {
    return -1;
  }
  if (pde & (1 << 7)) {
    pte = pde & ~0x003ff000;
    page_size = 4096 * 1024;
  } else {
    pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
    if (pte_addr > size) {
      return -1;
    }
    pte = *(unsigned *)((unsigned)mem + pte_addr);
    if (!(pte & (1 << 0))) {
      return -1;
    }
    page_size = 4096;
  }
  unsigned page_offset = addr & (page_size - 1);
  unsigned paddr = (pte & ~((1 << 12) - 1)) + page_offset;
  *rw = pte & (1 << 1);
  *us = pte & (1 << 2);
  *g = pte & (1 << 8);
  if (page_size == 0x400000)
    *ps = 1;
  else
    *ps = 0;
  return paddr;
}


x86 assembly (clang, -O0):
<vtopPageProperty>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    0x18(%rbp),%rax
mov    0x10(%rbp),%rax
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %edx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
mov    %r8,-0x28(%rbp)
mov    %r9,-0x30(%rbp)
mov    -0x18(%rbp),%eax
and    $0xfffff000,%eax
mov    -0x1c(%rbp),%ecx
shr    $0x14,%ecx
and    $0xfffffffc,%ecx
add    %ecx,%eax
mov    %eax,-0x34(%rbp)
mov    -0x34(%rbp),%eax
cmp    -0x14(%rbp),%eax
jbe    1175 <vtopPageProperty+0x65>
mov    -0x1c(%rbp),%esi
mov    -0x34(%rbp),%edx
lea    0xe9c(%rip),%rdi
call   1030 <printf@plt>
movl   $0xffffffff,-0x4(%rbp)
jmp    1296 <vtopPageProperty+0x186>
mov    -0x10(%rbp),%rax
add    -0x34(%rbp),%eax
mov    %eax,%eax
mov    (%rax),%eax
mov    %eax,-0x38(%rbp)
mov    -0x38(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
jne    119e <vtopPageProperty+0x8e>
movl   $0xffffffff,-0x4(%rbp)
jmp    1296 <vtopPageProperty+0x186>
mov    -0x38(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
je     11c6 <vtopPageProperty+0xb6>
mov    -0x38(%rbp),%eax
and    $0xffc00fff,%eax
mov    %eax,-0x3c(%rbp)
movl   $0x400000,-0x44(%rbp)
jmp    1227 <vtopPageProperty+0x117>
mov    -0x38(%rbp),%eax
and    $0xfffff000,%eax
mov    -0x1c(%rbp),%ecx
shr    $0xa,%ecx
and    $0xffc,%ecx
add    %ecx,%eax
mov    %eax,-0x40(%rbp)
mov    -0x40(%rbp),%eax
cmp    -0x14(%rbp),%eax
jbe    11f7 <vtopPageProperty+0xe7>
movl   $0xffffffff,-0x4(%rbp)
jmp    1296 <vtopPageProperty+0x186>
mov    -0x10(%rbp),%rax
add    -0x40(%rbp),%eax
mov    %eax,%eax
mov    (%rax),%eax
mov    %eax,-0x3c(%rbp)
mov    -0x3c(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
jne    1220 <vtopPageProperty+0x110>
movl   $0xffffffff,-0x4(%rbp)
jmp    1296 <vtopPageProperty+0x186>
movl   $0x1000,-0x44(%rbp)
mov    -0x1c(%rbp),%eax
mov    -0x44(%rbp),%ecx
sub    $0x1,%ecx
and    %ecx,%eax
mov    %eax,-0x48(%rbp)
mov    -0x3c(%rbp),%eax
and    $0xfffff000,%eax
add    -0x48(%rbp),%eax
mov    %eax,-0x4c(%rbp)
mov    -0x3c(%rbp),%ecx
and    $0x2,%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x3c(%rbp),%ecx
and    $0x4,%ecx
mov    -0x30(%rbp),%rax
mov    %ecx,(%rax)
mov    -0x3c(%rbp),%ecx
and    $0x100,%ecx
mov    0x10(%rbp),%rax
mov    %ecx,(%rax)
cmpl   $0x400000,-0x44(%rbp)
jne    1286 <vtopPageProperty+0x176>
mov    0x18(%rbp),%rax
movl   $0x1,(%rax)
jmp    1290 <vtopPageProperty+0x180>
mov    0x18(%rbp),%rax
movl   $0x0,(%rax)
mov    -0x4c(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<vtopPageProperty>:
push   %rbx
and    $0xfffff000,%edx
mov    %ecx,%eax
shr    $0x16,%eax
lea    (%rdx,%rax,4),%edx
cmp    %esi,%edx
jbe    1138 <vtopPageProperty+0x28>
lea    0xed6(%rip),%rdi
mov    %ecx,%esi
call   1030 <printf@plt>
mov    $0xffffffff,%eax
pop    %rbx
ret
add    %edi,%edx
mov    (%rdx),%r10d
mov    $0xffffffff,%eax
test   $0x1,%r10b
je     1179 <vtopPageProperty+0x69>
test   $0x80,%r10b
jne    117b <vtopPageProperty+0x6b>
mov    %r10d,%r11d
and    $0xfffff000,%r11d
mov    %ecx,%edx
shr    $0xa,%edx
and    $0xffc,%edx
or     %r11d,%edx
cmp    %esi,%edx
ja     1179 <vtopPageProperty+0x69>
add    %edi,%edx
mov    (%rdx),%esi
mov    $0xfff,%edi
test   $0x1,%sil
jne    1189 <vtopPageProperty+0x79>
pop    %rbx
ret
mov    %r10d,%esi
and    $0xffc00fff,%esi
mov    $0x3fffff,%edi
mov    0x18(%rsp),%r11
mov    0x10(%rsp),%rbx
movzbl %r10b,%edx
shr    $0x7,%edx
and    %ecx,%edi
mov    %esi,%eax
and    $0xfffff000,%eax
add    %edi,%eax
mov    %esi,%ecx
and    $0x2,%ecx
mov    %ecx,(%r8)
mov    %esi,%ecx
and    $0x4,%ecx
mov    %ecx,(%r9)
and    $0x100,%esi
mov    %esi,(%rbx)
mov    %edx,(%r11)
pop    %rbx
ret

LLVM IR (-O0):
@.str = [24 x i8] c"ERROR 1 addr %x pde %x\0A\00"
define i32 @vtopPageProperty(i8* %0, i32 %1, i32 %2, i32 %3, i32* %4, i32* %5, i32* %6, i32* %7) {
%9 = alloca i32
%10 = alloca i8*
%11 = alloca i32
%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 i32
%21 = alloca i32
%22 = alloca i32
%23 = alloca i32
%24 = alloca i32
store i8* %0, i8** %10
store i32 %1, i32* %11
store i32 %2, i32* %12
store i32 %3, i32* %13
store i32* %4, i32** %14
store i32* %5, i32** %15
store i32* %6, i32** %16
store i32* %7, i32** %17
%25 = load i32, i32* %12
%26 = and i32 %25, -4096
%27 = load i32, i32* %13
%28 = lshr i32 %27, 20
%29 = and i32 %28, -4
%30 = add i32 %26, %29
store i32 %30, i32* %18
%31 = load i32, i32* %18
%32 = load i32, i32* %11
%33 = icmp ugt i32 %31, %32
br i1 %33, label %34, label %38
34: ; preds = %8
%35 = load i32, i32* %13
%36 = load i32, i32* %18
%37 = call i32 @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str, i64 0, i64 0), i32 %35, i32 %36)
store i32 -1, i32* %9
br label %107
38: ; preds = %8
%39 = load i8*, i8** %10
%40 = ptrtoint i8* %39 to i32
%41 = load i32, i32* %18
%42 = add i32 %40, %41
%43 = zext i32 %42 to i64
%44 = inttoptr i64 %43 to i32*
%45 = load i32, i32* %44
store i32 %45, i32* %19
%46 = load i32, i32* %19
%47 = and i32 %46, 1
%48 = icmp ne i32 %47, 0
br i1 %48, label %50, label %49
49: ; preds = %38
store i32 -1, i32* %9
br label %107
50: ; preds = %38
%51 = load i32, i32* %19
%52 = and i32 %51, 128
%53 = icmp ne i32 %52, 0
br i1 %53, label %54, label %57
54: ; preds = %50
%55 = load i32, i32* %19
%56 = and i32 %55, -4190209
store i32 %56, i32* %20
store i32 4194304, i32* %22
br label %81
57: ; preds = %50
%58 = load i32, i32* %19
%59 = and i32 %58, -4096
%60 = load i32, i32* %13
%61 = lshr i32 %60, 10
%62 = and i32 %61, 4092
%63 = add i32 %59, %62
store i32 %63, i32* %21
%64 = load i32, i32* %21
%65 = load i32, i32* %11
%66 = icmp ugt i32 %64, %65
br i1 %66, label %67, label %68
67: ; preds = %57
store i32 -1, i32* %9
br label %107
68: ; preds = %57
%69 = load i8*, i8** %10
%70 = ptrtoint i8* %69 to i32
%71 = load i32, i32* %21
%72 = add i32 %70, %71
%73 = zext i32 %72 to i64
%74 = inttoptr i64 %73 to i32*
%75 = load i32, i32* %74
store i32 %75, i32* %20
%76 = load i32, i32* %20
%77 = and i32 %76, 1
%78 = icmp ne i32 %77, 0
br i1 %78, label %80, label %79
79: ; preds = %68
store i32 -1, i32* %9
br label %107
80: ; preds = %68
store i32 4096, i32* %22
br label %81
81: ; preds = %80, %54
%82 = load i32, i32* %13
%83 = load i32, i32* %22
%84 = sub i32 %83, 1
%85 = and i32 %82, %84
store i32 %85, i32* %23
%86 = load i32, i32* %20
%87 = and i32 %86, -4096
%88 = load i32, i32* %23
%89 = add i32 %87, %88
store i32 %89, i32* %24
%90 = load i32, i32* %20
%91 = and i32 %90, 2
%92 = load i32*, i32** %14
store i32 %91, i32* %92
%93 = load i32, i32* %20
%94 = and i32 %93, 4
%95 = load i32*, i32** %15
store i32 %94, i32* %95
%96 = load i32, i32* %20
%97 = and i32 %96, 256
%98 = load i32*, i32** %16
store i32 %97, i32* %98
%99 = load i32, i32* %22
%100 = icmp eq i32 %99, 4194304
br i1 %100, label %101, label %103
101: ; preds = %81
%102 = load i32*, i32** %17
store i32 1, i32* %102
br label %105
103: ; preds = %81
%104 = load i32*, i32** %17
store i32 0, i32* %104
br label %105
105: ; preds = %103, %101
%106 = load i32, i32* %24
store i32 %106, i32* %9
br label %107
107: ; preds = %105, %79, %67, %49, %34
%108 = load i32, i32* %9
ret i32 %108
}

LLVM IR (-O2):
@.str = [24 x i8] c"ERROR 1 addr %x pde %x\0A\00"
define i32 @vtopPageProperty(i8* %0, i32 %1, i32 %2, i32 %3, i32* nocapture writeonly %4, i32* nocapture writeonly %5, i32* nocapture writeonly %6, i32* nocapture writeonly %7) {
%9 = and i32 %2, -4096
%10 = lshr i32 %3, 20
%11 = and i32 %10, 4092
%12 = or i32 %11, %9
%13 = icmp ugt i32 %12, %1
br i1 %13, label %14, label %16
14: ; preds = %8
%15 = tail call i32 @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str, i64 0, i64 0), i32 %3, i32 %12)
br label %54
16: ; preds = %8
%17 = ptrtoint i8* %0 to i64
%18 = trunc i64 %17 to i32
%19 = add i32 %12, %18
%20 = zext i32 %19 to i64
%21 = inttoptr i64 %20 to i32*
%22 = load i32, i32* %21
%23 = and i32 %22, 1
%24 = icmp eq i32 %23, 0
br i1 %24, label %54, label %25
25: ; preds = %16
%26 = and i32 %22, 128
%27 = icmp eq i32 %26, 0
br i1 %27, label %30, label %28
28: ; preds = %25
%29 = and i32 %22, -4190209
br label %43
30: ; preds = %25
%31 = and i32 %22, -4096
%32 = lshr i32 %3, 10
%33 = and i32 %32, 4092
%34 = or i32 %31, %33
%35 = icmp ugt i32 %34, %1
br i1 %35, label %54, label %36
36: ; preds = %30
%37 = add i32 %34, %18
%38 = zext i32 %37 to i64
%39 = inttoptr i64 %38 to i32*
%40 = load i32, i32* %39
%41 = and i32 %40, 1
%42 = icmp eq i32 %41, 0
br i1 %42, label %54, label %43
43: ; preds = %36, %28
%44 = phi i32 [ %29, %28 ], [ %40, %36 ]
%45 = phi i32 [ 4194303, %28 ], [ 4095, %36 ]
%46 = and i32 %45, %3
%47 = and i32 %44, -4096
%48 = add i32 %46, %47
%49 = and i32 %44, 2
store i32 %49, i32* %4
%50 = and i32 %44, 4
store i32 %50, i32* %5
%51 = and i32 %44, 256
store i32 %51, i32* %6
%52 = xor i1 %27, true
%53 = zext i1 %52 to i32
store i32 %53, i32* %7
br label %54
54: ; preds = %43, %16, %30, %36, %14
%55 = phi i32 [ -1, %14 ], [ %48, %43 ], [ -1, %16 ], [ -1, %30 ], [ -1, %36 ]
ret i32 %55
}