#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 scramble(uint8_t *in, uint8_t *out, const int size) {
  static const 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];
    out[i] = val ^ in[i];
  }
}


x86 assembly (clang, -O0):
<scramble>:
push   %rbp
mov    %rsp,%rbp
sub    $0x7b0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
cmpl   $0x100,-0x18(%rbp)
jge    1164 <scramble+0x64>
mov    -0x18(%rbp),%ecx
movslq -0x18(%rbp),%rax
mov    %ecx,-0x430(%rbp,%rax,4)
mov    -0x18(%rbp),%eax
and    $0xf,%eax
movslq %eax,%rcx
lea    0xeb8(%rip),%rax
mov    (%rax,%rcx,4),%ecx
movslq -0x18(%rbp),%rax
mov    %ecx,-0x830(%rbp,%rax,4)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    111d <scramble+0x1d>
movl   $0x0,-0x1c(%rbp)
movl   $0x0,-0x18(%rbp)
cmpl   $0x100,-0x18(%rbp)
jge    11ec <scramble+0xec>
movslq -0x18(%rbp),%rax
mov    -0x430(%rbp,%rax,4),%eax
mov    %eax,-0x20(%rbp)
movslq -0x18(%rbp),%rax
mov    -0x430(%rbp,%rax,4),%eax
add    -0x1c(%rbp),%eax
mov    %eax,-0x1c(%rbp)
movslq -0x18(%rbp),%rax
mov    -0x830(%rbp,%rax,4),%eax
add    -0x1c(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
and    $0xff,%eax
mov    %eax,-0x1c(%rbp)
movslq -0x1c(%rbp),%rax
mov    -0x430(%rbp,%rax,4),%ecx
movslq -0x18(%rbp),%rax
mov    %ecx,-0x430(%rbp,%rax,4)
mov    -0x20(%rbp),%ecx
movslq -0x1c(%rbp),%rax
mov    %ecx,-0x430(%rbp,%rax,4)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1172 <scramble+0x72>
movl   $0x0,-0x28(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    12b8 <scramble+0x1b8>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
and    $0xff,%eax
cltq
mov    -0x430(%rbp,%rax,4),%eax
mov    %eax,-0x20(%rbp)
mov    -0x20(%rbp),%eax
mov    %eax,-0x24(%rbp)
mov    -0x20(%rbp),%eax
add    -0x28(%rbp),%eax
and    $0xff,%eax
mov    %eax,-0x28(%rbp)
movslq -0x28(%rbp),%rax
mov    -0x430(%rbp,%rax,4),%ecx
mov    -0x18(%rbp),%eax
add    $0x1,%eax
and    $0xff,%eax
cltq
mov    %ecx,-0x430(%rbp,%rax,4)
mov    -0x20(%rbp),%ecx
and    $0xff,%ecx
movslq -0x28(%rbp),%rax
mov    %ecx,-0x430(%rbp,%rax,4)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
and    $0xff,%eax
cltq
mov    -0x430(%rbp,%rax,4),%eax
add    -0x20(%rbp),%eax
and    $0xff,%eax
mov    %eax,-0x24(%rbp)
movslq -0x24(%rbp),%rax
mov    -0x430(%rbp,%rax,4),%eax
mov    %eax,-0x24(%rbp)
mov    -0x24(%rbp),%edx
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
xor    (%rax,%rcx,4),%edx
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    11fa <scramble+0xfa>
add    $0x7b0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<scramble>:
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 <scramble+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 <scramble+0x50>
test   %edx,%edx
jle    1208 <scramble+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 <scramble+0xc0>
add    $0x788,%rsp
ret

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

LLVM IR (-O2):
@scramble.key = internal unnamed_addr constant [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 @scramble(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]* @scramble.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]* @scramble.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
}