#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;
typedef scalar_t__ uint64_t;

/* Variables and functions */
int /*<<< orphan*/ memcpy(scalar_t__ *, int const *, int);
int /*<<< orphan*/ memset(scalar_t__ *, int, int);
int /*<<< orphan*/ morus_stateupdate(scalar_t__ *, scalar_t__ **);
void morus_initialization(const uint8_t *key, const uint8_t *iv,
                          uint64_t state[][4]) {
  int i;
  uint64_t temp[4] = {0, 0, 0, 0};
  uint8_t con[32] = {0x0,  0x1,  0x01, 0x02, 0x03, 0x05, 0x08, 0x0d,
                     0x15, 0x22, 0x37, 0x59, 0x90, 0xe9, 0x79, 0x62,
                     0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1,
                     0x20, 0x11, 0x31, 0x42, 0x73, 0xb5, 0x28, 0xdd};
  memcpy(state[0], iv, 16);
  memset(state[0] + 2, 0, 16);
  memcpy(state[1], key, 32);
  memset(state[2], 0xff, 32);
  memset(state[3], 0, 32);
  memcpy(state[4], con, 32);
  for (i = 0; i < 4; i++)
    temp[i] = 0;
  for (i = 0; i < 16; i++)
    morus_stateupdate(temp, state);
  for (i = 0; i < 4; i++)
    state[1][i] ^= ((uint64_t *)key)[i];
}


x86 assembly (clang, -O0):
<morus_initialization>:
push   %rbp
mov    %rsp,%rbp
sub    $0xc0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
lea    -0x40(%rbp),%rdi
xor    %esi,%esi
mov    $0x20,%edx
call   1030 <memset@plt>
lea    -0xc0(%rbp),%rdi
lea    0xe9b(%rip),%rsi
mov    $0x80,%edx
call   1040 <memcpy@plt>
mov    -0x18(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    $0x10,%edx
call   1040 <memcpy@plt>
mov    -0x18(%rbp),%rdi
add    $0x10,%rdi
xor    %esi,%esi
mov    $0x10,%edx
call   1030 <memset@plt>
mov    -0x18(%rbp),%rdi
add    $0x20,%rdi
mov    -0x8(%rbp),%rsi
mov    $0x20,%edx
call   1040 <memcpy@plt>
mov    -0x18(%rbp),%rdi
add    $0x40,%rdi
mov    $0xff,%esi
mov    $0x20,%edx
call   1030 <memset@plt>
mov    -0x18(%rbp),%rdi
add    $0x60,%rdi
xor    %esi,%esi
mov    $0x20,%edx
call   1030 <memset@plt>
mov    -0x18(%rbp),%rdi
add    $0x80,%rdi
lea    -0xc0(%rbp),%rsi
mov    $0x20,%edx
call   1040 <memcpy@plt>
movl   $0x0,-0x1c(%rbp)
cmpl   $0x4,-0x1c(%rbp)
jge    121e <morus_initialization+0xee>
movslq -0x1c(%rbp),%rax
movq   $0x0,-0x40(%rbp,%rax,8)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    11f9 <morus_initialization+0xc9>
movl   $0x0,-0x1c(%rbp)
cmpl   $0x10,-0x1c(%rbp)
jge    124a <morus_initialization+0x11a>
lea    -0x40(%rbp),%rdi
mov    -0x18(%rbp),%rsi
call   1050 <morus_stateupdate@plt>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1225 <morus_initialization+0xf5>
movl   $0x0,-0x1c(%rbp)
cmpl   $0x4,-0x1c(%rbp)
jge    1287 <morus_initialization+0x157>
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    (%rax,%rcx,8),%rdx
mov    -0x18(%rbp),%rax
movslq -0x1c(%rbp),%rcx
xor    0x20(%rax,%rcx,8),%rdx
mov    %rdx,0x20(%rax,%rcx,8)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1251 <morus_initialization+0x121>
add    $0xc0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<morus_initialization>:
push   %r15
push   %r14
push   %rbx
sub    $0xa0,%rsp
mov    %rdx,%rbx
mov    %rdi,%r14
movaps 0xf27(%rip),%xmm0
movaps %xmm0,0x90(%rsp)
movaps 0xf08(%rip),%xmm0
movaps %xmm0,0x80(%rsp)
movaps 0xee9(%rip),%xmm0
movaps %xmm0,0x70(%rsp)
movaps 0xecd(%rip),%xmm0
movaps %xmm0,0x60(%rsp)
movaps 0xeb1(%rip),%xmm0
movaps %xmm0,0x50(%rsp)
movaps 0xe95(%rip),%xmm0
movaps %xmm0,0x40(%rsp)
movaps 0xe79(%rip),%xmm0
movaps %xmm0,0x30(%rsp)
movaps 0xe5d(%rip),%xmm0
movaps %xmm0,0x20(%rsp)
mov    %rdx,%rdi
mov    $0x10,%edx
call   1040 <memcpy@plt>
lea    0x10(%rbx),%rdi
xor    %esi,%esi
mov    $0x10,%edx
call   1030 <memset@plt>
lea    0x20(%rbx),%rdi
mov    %r14,%rsi
mov    $0x20,%edx
call   1040 <memcpy@plt>
lea    0x40(%rbx),%rdi
mov    $0xff,%esi
mov    $0x20,%edx
call   1030 <memset@plt>
lea    0x60(%rbx),%rdi
xor    %esi,%esi
mov    $0x20,%edx
call   1030 <memset@plt>
lea    0x80(%rbx),%rdi
lea    0x20(%rsp),%rsi
mov    $0x20,%edx
call   1040 <memcpy@plt>
xorps  %xmm0,%xmm0
movaps %xmm0,(%rsp)
movaps %xmm0,0x10(%rsp)
mov    %rsp,%r15
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
call   1050 <morus_stateupdate@plt>
mov    (%r14),%rax
xor    %rax,0x20(%rbx)
mov    0x8(%r14),%rax
xor    %rax,0x28(%rbx)
mov    0x10(%r14),%rax
xor    %rax,0x30(%rbx)
mov    0x18(%r14),%rax
xor    %rax,0x38(%rbx)
add    $0xa0,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@__const.morus_initialization.con = [32 x i32] [i32 0, i32 1, i32 1, i32 2, i32 3, i32 5, i32 8, i32 13, i32 21, i32 34, i32 55, i32 89, i32 144, i32 233, i32 121, i32 98, i32 219, i32 61, i32 24, i32 85, i32 109, i32 194, i32 47, i32 241, i32 32, i32 17, i32 49, i32 66, i32 115, i32 181, i32 40, i32 221]
define void @morus_initialization(i32* %0, i32* %1, [4 x i64]* %2) {
%4 = alloca i32*
%5 = alloca i32*
%6 = alloca [4 x i64]*
%7 = alloca i32
%8 = alloca [4 x i64]
%9 = alloca [32 x i32]
store i32* %0, i32** %4
store i32* %1, i32** %5
store [4 x i64]* %2, [4 x i64]** %6
%10 = bitcast [4 x i64]* %8 to i8*
%11 = bitcast [32 x i32]* %9 to i8*
%12 = load [4 x i64]*, [4 x i64]** %6
%13 = getelementptr inbounds [4 x i64], [4 x i64]* %12, i64 0
%14 = getelementptr inbounds [4 x i64], [4 x i64]* %13, i64 0, i64 0
%15 = load i32*, i32** %5
%16 = call i32 @memcpy(i64* %14, i32* %15, i32 16)
%17 = load [4 x i64]*, [4 x i64]** %6
%18 = getelementptr inbounds [4 x i64], [4 x i64]* %17, i64 0
%19 = getelementptr inbounds [4 x i64], [4 x i64]* %18, i64 0, i64 0
%20 = getelementptr inbounds i64, i64* %19, i64 2
%21 = call i32 @memset(i64* %20, i32 0, i32 16)
%22 = load [4 x i64]*, [4 x i64]** %6
%23 = getelementptr inbounds [4 x i64], [4 x i64]* %22, i64 1
%24 = getelementptr inbounds [4 x i64], [4 x i64]* %23, i64 0, i64 0
%25 = load i32*, i32** %4
%26 = call i32 @memcpy(i64* %24, i32* %25, i32 32)
%27 = load [4 x i64]*, [4 x i64]** %6
%28 = getelementptr inbounds [4 x i64], [4 x i64]* %27, i64 2
%29 = getelementptr inbounds [4 x i64], [4 x i64]* %28, i64 0, i64 0
%30 = call i32 @memset(i64* %29, i32 255, i32 32)
%31 = load [4 x i64]*, [4 x i64]** %6
%32 = getelementptr inbounds [4 x i64], [4 x i64]* %31, i64 3
%33 = getelementptr inbounds [4 x i64], [4 x i64]* %32, i64 0, i64 0
%34 = call i32 @memset(i64* %33, i32 0, i32 32)
%35 = load [4 x i64]*, [4 x i64]** %6
%36 = getelementptr inbounds [4 x i64], [4 x i64]* %35, i64 4
%37 = getelementptr inbounds [4 x i64], [4 x i64]* %36, i64 0, i64 0
%38 = getelementptr inbounds [32 x i32], [32 x i32]* %9, i64 0, i64 0
%39 = call i32 @memcpy(i64* %37, i32* %38, i32 32)
store i32 0, i32* %7
br label %40
40: ; preds = %47, %3
%41 = load i32, i32* %7
%42 = icmp slt i32 %41, 4
br i1 %42, label %43, label %50
43: ; preds = %40
%44 = load i32, i32* %7
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds [4 x i64], [4 x i64]* %8, i64 0, i64 %45
store i64 0, i64* %46
br label %47
47: ; preds = %43
%48 = load i32, i32* %7
%49 = add nsw i32 %48, 1
store i32 %49, i32* %7
br label %40
50: ; preds = %40
store i32 0, i32* %7
br label %51
51: ; preds = %59, %50
%52 = load i32, i32* %7
%53 = icmp slt i32 %52, 16
br i1 %53, label %54, label %62
54: ; preds = %51
%55 = getelementptr inbounds [4 x i64], [4 x i64]* %8, i64 0, i64 0
%56 = load [4 x i64]*, [4 x i64]** %6
%57 = bitcast [4 x i64]* %56 to i64**
%58 = call i32 @morus_stateupdate(i64* %55, i64** %57)
br label %59
59: ; preds = %54
%60 = load i32, i32* %7
%61 = add nsw i32 %60, 1
store i32 %61, i32* %7
br label %51
62: ; preds = %51
store i32 0, i32* %7
br label %63
63: ; preds = %80, %62
%64 = load i32, i32* %7
%65 = icmp slt i32 %64, 4
br i1 %65, label %66, label %83
66: ; preds = %63
%67 = load i32*, i32** %4
%68 = bitcast i32* %67 to i64*
%69 = load i32, i32* %7
%70 = sext i32 %69 to i64
%71 = getelementptr inbounds i64, i64* %68, i64 %70
%72 = load i64, i64* %71
%73 = load [4 x i64]*, [4 x i64]** %6
%74 = getelementptr inbounds [4 x i64], [4 x i64]* %73, i64 1
%75 = load i32, i32* %7
%76 = sext i32 %75 to i64
%77 = getelementptr inbounds [4 x i64], [4 x i64]* %74, i64 0, i64 %76
%78 = load i64, i64* %77
%79 = xor i64 %78, %72
store i64 %79, i64* %77
br label %80
80: ; preds = %66
%81 = load i32, i32* %7
%82 = add nsw i32 %81, 1
store i32 %82, i32* %7
br label %63
83: ; preds = %63
ret void
}

LLVM IR (-O2):
@__const.morus_initialization.con = [32 x i32] [i32 0, i32 1, i32 1, i32 2, i32 3, i32 5, i32 8, i32 13, i32 21, i32 34, i32 55, i32 89, i32 144, i32 233, i32 121, i32 98, i32 219, i32 61, i32 24, i32 85, i32 109, i32 194, i32 47, i32 241, i32 32, i32 17, i32 49, i32 66, i32 115, i32 181, i32 40, i32 221]
define void @morus_initialization(i32* %0, i32* %1, [4 x i64]* %2) {
%4 = alloca [4 x i64]
%5 = bitcast [4 x i64]* %4 to i8*
%6 = alloca [32 x i32]
%7 = bitcast [32 x i32]* %6 to i8*
%8 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 0, i64 0
%9 = tail call i32 @memcpy(i64* %8, i32* %1, i32 16)
%10 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 0, i64 2
%11 = tail call i32 @memset(i64* %10, i32 0, i32 16)
%12 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 1, i64 0
%13 = tail call i32 @memcpy(i64* %12, i32* %0, i32 32)
%14 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 2, i64 0
%15 = tail call i32 @memset(i64* %14, i32 255, i32 32)
%16 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 3, i64 0
%17 = tail call i32 @memset(i64* %16, i32 0, i32 32)
%18 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 4, i64 0
%19 = getelementptr inbounds [32 x i32], [32 x i32]* %6, i64 0, i64 0
%20 = call i32 @memcpy(i64* %18, i32* %19, i32 32)
%21 = getelementptr inbounds [4 x i64], [4 x i64]* %4, i64 0, i64 0
%22 = bitcast [4 x i64]* %2 to i64**
%23 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%24 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%25 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%26 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%27 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%28 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%29 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%30 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%31 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%32 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%33 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%34 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%35 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%36 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%37 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%38 = call i32 @morus_stateupdate(i64* %21, i64** %22)
%39 = bitcast i32* %0 to i64*
%40 = load i64, i64* %39
%41 = load i64, i64* %12
%42 = xor i64 %41, %40
store i64 %42, i64* %12
%43 = getelementptr inbounds i32, i32* %0, i64 2
%44 = bitcast i32* %43 to i64*
%45 = load i64, i64* %44
%46 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 1, i64 1
%47 = load i64, i64* %46
%48 = xor i64 %47, %45
store i64 %48, i64* %46
%49 = getelementptr inbounds i32, i32* %0, i64 4
%50 = bitcast i32* %49 to i64*
%51 = load i64, i64* %50
%52 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 1, i64 2
%53 = load i64, i64* %52
%54 = xor i64 %53, %51
store i64 %54, i64* %52
%55 = getelementptr inbounds i32, i32* %0, i64 6
%56 = bitcast i32* %55 to i64*
%57 = load i64, i64* %56
%58 = getelementptr inbounds [4 x i64], [4 x i64]* %2, i64 1, i64 3
%59 = load i64, i64* %58
%60 = xor i64 %59, %57
store i64 %60, i64* %58
ret void
}