#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 uint8_t;

/* Variables and functions */
void encode_page(uint8_t *inpg, uint8_t *outpg, const int size) {
  uint8_t key[] = {0x7C, 0x4E, 0x03, 0x04, 0x55, 0x05, 0x09, 0x07,
                   0x2D, 0x2C, 0x7B, 0x38, 0x17, 0x0D, 0x17, 0x11};
  int i, i3, x, val, idx;
  uint8_t key1[0x100];
  uint8_t key2[0x100];
  for (i = 0; i < 0x100; i++) {
    key1[i] = i;
    key2[i] = key[i & 0xf];
  }
  i3 = 0;
  for (i = 0; i < 0x100; i++) {
    x = key1[i];
    i3 = key1[i] + i3;
    i3 += key2[i];
    i3 &= 0xff;
    key1[i] = key1[i3];
    key1[i3] = x;
  }
  idx = 0;
  for (i = 0; i < size; i++) {
    x = key1[(i + 1) & 0xff];
    val = x;
    idx = (x + idx) & 0xff;
    key1[(i + 1) & 0xff] = key1[idx];
    key1[idx] = (x & 0xff);
    val = (key1[(i + 1) & 0xff] + x) & 0xff;
    val = key1[val];
    outpg[i] = val ^ inpg[i];
  }
}


x86 assembly (clang, -O0):
<encode_page>:
push   %rbp
mov    %rsp,%rbp
sub    $0x880,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
lea    -0x60(%rbp),%rdi
lea    0xecf(%rip),%rsi
mov    $0x40,%edx
call   1030 <memcpy@plt>
movl   $0x0,-0x64(%rbp)
cmpl   $0x100,-0x64(%rbp)
jge    1182 <encode_page+0x72>
mov    -0x64(%rbp),%ecx
movslq -0x64(%rbp),%rax
mov    %ecx,-0x480(%rbp,%rax,4)
mov    -0x64(%rbp),%eax
and    $0xf,%eax
cltq
mov    -0x60(%rbp,%rax,4),%ecx
movslq -0x64(%rbp),%rax
mov    %ecx,-0x880(%rbp,%rax,4)
mov    -0x64(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x64(%rbp)
jmp    1142 <encode_page+0x32>
movl   $0x0,-0x68(%rbp)
movl   $0x0,-0x64(%rbp)
cmpl   $0x100,-0x64(%rbp)
jge    120a <encode_page+0xfa>
movslq -0x64(%rbp),%rax
mov    -0x480(%rbp,%rax,4),%eax
mov    %eax,-0x6c(%rbp)
movslq -0x64(%rbp),%rax
mov    -0x480(%rbp,%rax,4),%eax
add    -0x68(%rbp),%eax
mov    %eax,-0x68(%rbp)
movslq -0x64(%rbp),%rax
mov    -0x880(%rbp,%rax,4),%eax
add    -0x68(%rbp),%eax
mov    %eax,-0x68(%rbp)
mov    -0x68(%rbp),%eax
and    $0xff,%eax
mov    %eax,-0x68(%rbp)
movslq -0x68(%rbp),%rax
mov    -0x480(%rbp,%rax,4),%ecx
movslq -0x64(%rbp),%rax
mov    %ecx,-0x480(%rbp,%rax,4)
mov    -0x6c(%rbp),%ecx
movslq -0x68(%rbp),%rax
mov    %ecx,-0x480(%rbp,%rax,4)
mov    -0x64(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x64(%rbp)
jmp    1190 <encode_page+0x80>
movl   $0x0,-0x74(%rbp)
movl   $0x0,-0x64(%rbp)
mov    -0x64(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    12d6 <encode_page+0x1c6>
mov    -0x64(%rbp),%eax
add    $0x1,%eax
and    $0xff,%eax
cltq
mov    -0x480(%rbp,%rax,4),%eax
mov    %eax,-0x6c(%rbp)
mov    -0x6c(%rbp),%eax
mov    %eax,-0x70(%rbp)
mov    -0x6c(%rbp),%eax
add    -0x74(%rbp),%eax
and    $0xff,%eax
mov    %eax,-0x74(%rbp)
movslq -0x74(%rbp),%rax
mov    -0x480(%rbp,%rax,4),%ecx
mov    -0x64(%rbp),%eax
add    $0x1,%eax
and    $0xff,%eax
cltq
mov    %ecx,-0x480(%rbp,%rax,4)
mov    -0x6c(%rbp),%ecx
and    $0xff,%ecx
movslq -0x74(%rbp),%rax
mov    %ecx,-0x480(%rbp,%rax,4)
mov    -0x64(%rbp),%eax
add    $0x1,%eax
and    $0xff,%eax
cltq
mov    -0x480(%rbp,%rax,4),%eax
add    -0x6c(%rbp),%eax
and    $0xff,%eax
mov    %eax,-0x70(%rbp)
movslq -0x70(%rbp),%rax
mov    -0x480(%rbp,%rax,4),%eax
mov    %eax,-0x70(%rbp)
mov    -0x70(%rbp),%edx
mov    -0x8(%rbp),%rax
movslq -0x64(%rbp),%rcx
xor    (%rax,%rcx,4),%edx
mov    -0x10(%rbp),%rax
movslq -0x64(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x64(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x64(%rbp)
jmp    1218 <encode_page+0x108>
add    $0x880,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<encode_page>:
sub    $0x788,%rsp
xor    %ecx,%ecx
lea    0xef0(%rip),%r8
mov    %ecx,-0x80(%rsp,%rcx,4)
mov    %ecx,%eax
and    $0xe,%eax
mov    (%r8,%rax,4),%eax
mov    %eax,0x380(%rsp,%rcx,4)
lea    0x1(%rcx),%rax
mov    %eax,-0x7c(%rsp,%rcx,4)
and    $0xf,%eax
mov    (%r8,%rax,4),%eax
mov    %eax,0x384(%rsp,%rcx,4)
add    $0x2,%rcx
cmp    $0x100,%rcx
jne    1110 <encode_page+0x10>
xor    %r10d,%r10d
xor    %ecx,%ecx
nopl   0x0(%rax)
mov    -0x80(%rsp,%r10,4),%r8d
add    %r8d,%ecx
add    0x380(%rsp,%r10,4),%ecx
movzbl %cl,%r9d
mov    -0x80(%rsp,%r9,4),%eax
mov    %eax,-0x80(%rsp,%r10,4)
mov    %r8d,-0x80(%rsp,%r9,4)
mov    -0x7c(%rsp,%r10,4),%r8d
add    %r8d,%ecx
add    0x384(%rsp,%r10,4),%ecx
movzbl %cl,%ecx
mov    -0x80(%rsp,%rcx,4),%eax
mov    %eax,-0x7c(%rsp,%r10,4)
mov    %r8d,-0x80(%rsp,%rcx,4)
add    $0x2,%r10
cmp    $0x100,%r10
jne    1150 <encode_page+0x50>
test   %edx,%edx
jle    1208 <encode_page+0x108>
mov    %edx,%r8d
neg    %r8
xor    %ecx,%ecx
mov    $0x1,%edx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movzbl %dl,%r9d
mov    -0x80(%rsp,%r9,4),%r10d
add    %r10d,%ecx
movzbl %cl,%ecx
mov    -0x80(%rsp,%rcx,4),%eax
mov    %eax,-0x80(%rsp,%r9,4)
movzbl %r10b,%eax
mov    %eax,-0x80(%rsp,%rcx,4)
add    -0x80(%rsp,%r9,4),%r10d
movzbl %r10b,%r9d
mov    -0x4(%rdi,%rdx,4),%eax
xor    -0x80(%rsp,%r9,4),%eax
mov    %eax,-0x4(%rsi,%rdx,4)
lea    (%r8,%rdx,1),%rax
add    $0x1,%rax
add    $0x1,%rdx
cmp    $0x1,%rax
jne    11c0 <encode_page+0xc0>
add    $0x788,%rsp
ret

LLVM IR (-O0):
@__const.encode_page.key = [16 x i32] [i32 124, i32 78, i32 3, i32 4, i32 85, i32 5, i32 9, i32 7, i32 45, i32 44, i32 123, i32 56, i32 23, i32 13, i32 23, i32 17]
define void @encode_page(i32* %0, i32* %1, i32 %2) {
%4 = alloca i32*
%5 = alloca i32*
%6 = alloca i32
%7 = alloca [16 x i32]
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca [256 x i32]
%14 = alloca [256 x i32]
store i32* %0, i32** %4
store i32* %1, i32** %5
store i32 %2, i32* %6
%15 = bitcast [16 x i32]* %7 to i8*
store i32 0, i32* %8
br label %16
16: ; preds = %32, %3
%17 = load i32, i32* %8
%18 = icmp slt i32 %17, 256
br i1 %18, label %19, label %35
19: ; preds = %16
%20 = load i32, i32* %8
%21 = load i32, i32* %8
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %22
store i32 %20, i32* %23
%24 = load i32, i32* %8
%25 = and i32 %24, 15
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds [16 x i32], [16 x i32]* %7, i64 0, i64 %26
%28 = load i32, i32* %27
%29 = load i32, i32* %8
%30 = sext i32 %29 to i64
%31 = getelementptr inbounds [256 x i32], [256 x i32]* %14, i64 0, i64 %30
store i32 %28, i32* %31
br label %32
32: ; preds = %19
%33 = load i32, i32* %8
%34 = add nsw i32 %33, 1
store i32 %34, i32* %8
br label %16
35: ; preds = %16
store i32 0, i32* %9
store i32 0, i32* %8
br label %36
36: ; preds = %69, %35
%37 = load i32, i32* %8
%38 = icmp slt i32 %37, 256
br i1 %38, label %39, label %72
39: ; preds = %36
%40 = load i32, i32* %8
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %41
%43 = load i32, i32* %42
store i32 %43, i32* %10
%44 = load i32, i32* %8
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %45
%47 = load i32, i32* %46
%48 = load i32, i32* %9
%49 = add nsw i32 %47, %48
store i32 %49, i32* %9
%50 = load i32, i32* %8
%51 = sext i32 %50 to i64
%52 = getelementptr inbounds [256 x i32], [256 x i32]* %14, i64 0, i64 %51
%53 = load i32, i32* %52
%54 = load i32, i32* %9
%55 = add nsw i32 %54, %53
store i32 %55, i32* %9
%56 = load i32, i32* %9
%57 = and i32 %56, 255
store i32 %57, i32* %9
%58 = load i32, i32* %9
%59 = sext i32 %58 to i64
%60 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %59
%61 = load i32, i32* %60
%62 = load i32, i32* %8
%63 = sext i32 %62 to i64
%64 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %63
store i32 %61, i32* %64
%65 = load i32, i32* %10
%66 = load i32, i32* %9
%67 = sext i32 %66 to i64
%68 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %67
store i32 %65, i32* %68
br label %69
69: ; preds = %39
%70 = load i32, i32* %8
%71 = add nsw i32 %70, 1
store i32 %71, i32* %8
br label %36
72: ; preds = %36
store i32 0, i32* %12
store i32 0, i32* %8
br label %73
73: ; preds = %127, %72
%74 = load i32, i32* %8
%75 = load i32, i32* %6
%76 = icmp slt i32 %74, %75
br i1 %76, label %77, label %130
77: ; preds = %73
%78 = load i32, i32* %8
%79 = add nsw i32 %78, 1
%80 = and i32 %79, 255
%81 = sext i32 %80 to i64
%82 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %81
%83 = load i32, i32* %82
store i32 %83, i32* %10
%84 = load i32, i32* %10
store i32 %84, i32* %11
%85 = load i32, i32* %10
%86 = load i32, i32* %12
%87 = add nsw i32 %85, %86
%88 = and i32 %87, 255
store i32 %88, i32* %12
%89 = load i32, i32* %12
%90 = sext i32 %89 to i64
%91 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %90
%92 = load i32, i32* %91
%93 = load i32, i32* %8
%94 = add nsw i32 %93, 1
%95 = and i32 %94, 255
%96 = sext i32 %95 to i64
%97 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %96
store i32 %92, i32* %97
%98 = load i32, i32* %10
%99 = and i32 %98, 255
%100 = load i32, i32* %12
%101 = sext i32 %100 to i64
%102 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %101
store i32 %99, i32* %102
%103 = load i32, i32* %8
%104 = add nsw i32 %103, 1
%105 = and i32 %104, 255
%106 = sext i32 %105 to i64
%107 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %106
%108 = load i32, i32* %107
%109 = load i32, i32* %10
%110 = add nsw i32 %108, %109
%111 = and i32 %110, 255
store i32 %111, i32* %11
%112 = load i32, i32* %11
%113 = sext i32 %112 to i64
%114 = getelementptr inbounds [256 x i32], [256 x i32]* %13, i64 0, i64 %113
%115 = load i32, i32* %114
store i32 %115, i32* %11
%116 = load i32, i32* %11
%117 = load i32*, i32** %4
%118 = load i32, i32* %8
%119 = sext i32 %118 to i64
%120 = getelementptr inbounds i32, i32* %117, i64 %119
%121 = load i32, i32* %120
%122 = xor i32 %116, %121
%123 = load i32*, i32** %5
%124 = load i32, i32* %8
%125 = sext i32 %124 to i64
%126 = getelementptr inbounds i32, i32* %123, i64 %125
store i32 %122, i32* %126
br label %127
127: ; preds = %77
%128 = load i32, i32* %8
%129 = add nsw i32 %128, 1
store i32 %129, i32* %8
br label %73
130: ; preds = %73
ret void
}

LLVM IR (-O2):
@__const.encode_page.key = [16 x i32] [i32 124, i32 78, i32 3, i32 4, i32 85, i32 5, i32 9, i32 7, i32 45, i32 44, i32 123, i32 56, i32 23, i32 13, i32 23, i32 17]
define void @encode_page(i32* nocapture %0, i32* nocapture writeonly %1, i32 %2) {
%4 = alloca [256 x i32]
%5 = alloca [256 x i32]
%6 = bitcast [256 x i32]* %4 to i8*
%7 = bitcast [256 x i32]* %5 to i8*
br label %8
8: ; preds = %8, %3
%9 = phi i64 [ 0, %3 ], [ %23, %8 ]
%10 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %9
%11 = trunc i64 %9 to i32
store i32 %11, i32* %10
%12 = and i64 %9, 14
%13 = getelementptr inbounds [16 x i32], [16 x i32]* @__const.encode_page.key, i64 0, i64 %12
%14 = load i32, i32* %13
%15 = getelementptr inbounds [256 x i32], [256 x i32]* %5, i64 0, i64 %9
store i32 %14, i32* %15
%16 = or i64 %9, 1
%17 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %16
%18 = trunc i64 %16 to i32
store i32 %18, i32* %17
%19 = and i64 %16, 15
%20 = getelementptr inbounds [16 x i32], [16 x i32]* @__const.encode_page.key, i64 0, i64 %19
%21 = load i32, i32* %20
%22 = getelementptr inbounds [256 x i32], [256 x i32]* %5, i64 0, i64 %16
store i32 %21, i32* %22
%23 = add nuw nsw i64 %9, 2
%24 = icmp eq i64 %23, 256
br i1 %24, label %29, label %8
25: ; preds = %29
%26 = icmp sgt i32 %2, 0
br i1 %26, label %27, label %79
27: ; preds = %25
%28 = zext i32 %2 to i64
br label %55
29: ; preds = %8, %29
%30 = phi i64 [ %53, %29 ], [ 0, %8 ]
%31 = phi i32 [ %49, %29 ], [ 0, %8 ]
%32 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %30
%33 = load i32, i32* %32
%34 = add nsw i32 %33, %31
%35 = getelementptr inbounds [256 x i32], [256 x i32]* %5, i64 0, i64 %30
%36 = load i32, i32* %35
%37 = add nsw i32 %34, %36
%38 = and i32 %37, 255
%39 = zext i32 %38 to i64
%40 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %39
%41 = load i32, i32* %40
store i32 %41, i32* %32
store i32 %33, i32* %40
%42 = or i64 %30, 1
%43 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %42
%44 = load i32, i32* %43
%45 = add i32 %44, %37
%46 = getelementptr inbounds [256 x i32], [256 x i32]* %5, i64 0, i64 %42
%47 = load i32, i32* %46
%48 = add i32 %45, %47
%49 = and i32 %48, 255
%50 = zext i32 %49 to i64
%51 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %50
%52 = load i32, i32* %51
store i32 %52, i32* %43
store i32 %44, i32* %51
%53 = add nuw nsw i64 %30, 2
%54 = icmp eq i64 %53, 256
br i1 %54, label %25, label %29
55: ; preds = %27, %55
%56 = phi i64 [ 0, %27 ], [ %58, %55 ]
%57 = phi i32 [ 0, %27 ], [ %63, %55 ]
%58 = add nuw nsw i64 %56, 1
%59 = and i64 %58, 255
%60 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %59
%61 = load i32, i32* %60
%62 = add nsw i32 %61, %57
%63 = and i32 %62, 255
%64 = zext i32 %63 to i64
%65 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %64
%66 = load i32, i32* %65
store i32 %66, i32* %60
%67 = and i32 %61, 255
store i32 %67, i32* %65
%68 = load i32, i32* %60
%69 = add nsw i32 %68, %61
%70 = and i32 %69, 255
%71 = zext i32 %70 to i64
%72 = getelementptr inbounds [256 x i32], [256 x i32]* %4, i64 0, i64 %71
%73 = load i32, i32* %72
%74 = getelementptr inbounds i32, i32* %0, i64 %56
%75 = load i32, i32* %74
%76 = xor i32 %75, %73
%77 = getelementptr inbounds i32, i32* %1, i64 %56
store i32 %76, i32* %77
%78 = icmp eq i64 %58, %28
br i1 %78, label %79, label %55
79: ; preds = %55, %25
ret void
}