// File: /workspace/github_cpp_makefile_star2_O2/twekkel[P]mzpq/libzpaq.cpp
// Function: libzpaq::AES_CTR::AES_CTR(char const*, int, char const*)
AES_CTR::AES_CTR(const char* key, int keylen, const char* iv) {
  assert(key  != NULL);
  assert(keylen==16 || keylen==24 || keylen==32);

  // Initialize IV (default 0)
  iv0=iv1=0;
  if (iv) {
    LOAD32H(iv0, iv);
    LOAD32H(iv1, iv+4);
  }

  // Initialize encryption tables
  for (int i=0; i<256; ++i) {
    unsigned s1=
    "\x63\x7c\x77\x7b\xf2\x6b\x6f\xc5\x30\x01\x67\x2b\xfe\xd7\xab\x76"
    "\xca\x82\xc9\x7d\xfa\x59\x47\xf0\xad\xd4\xa2\xaf\x9c\xa4\x72\xc0"
    "\xb7\xfd\x93\x26\x36\x3f\xf7\xcc\x34\xa5\xe5\xf1\x71\xd8\x31\x15"
    "\x04\xc7\x23\xc3\x18\x96\x05\x9a\x07\x12\x80\xe2\xeb\x27\xb2\x75"
    "\x09\x83\x2c\x1a\x1b\x6e\x5a\xa0\x52\x3b\xd6\xb3\x29\xe3\x2f\x84"
    "\x53\xd1\x00\xed\x20\xfc\xb1\x5b\x6a\xcb\xbe\x39\x4a\x4c\x58\xcf"
    "\xd0\xef\xaa\xfb\x43\x4d\x33\x85\x45\xf9\x02\x7f\x50\x3c\x9f\xa8"
    "\x51\xa3\x40\x8f\x92\x9d\x38\xf5\xbc\xb6\xda\x21\x10\xff\xf3\xd2"
    "\xcd\x0c\x13\xec\x5f\x97\x44\x17\xc4\xa7\x7e\x3d\x64\x5d\x19\x73"
    "\x60\x81\x4f\xdc\x22\x2a\x90\x88\x46\xee\xb8\x14\xde\x5e\x0b\xdb"
    "\xe0\x32\x3a\x0a\x49\x06\x24\x5c\xc2\xd3\xac\x62\x91\x95\xe4\x79"
    "\xe7\xc8\x37\x6d\x8d\xd5\x4e\xa9\x6c\x56\xf4\xea\x65\x7a\xae\x08"
    "\xba\x78\x25\x2e\x1c\xa6\xb4\xc6\xe8\xdd\x74\x1f\x4b\xbd\x8b\x8a"
    "\x70\x3e\xb5\x66\x48\x03\xf6\x0e\x61\x35\x57\xb9\x86\xc1\x1d\x9e"
    "\xe1\xf8\x98\x11\x69\xd9\x8e\x94\x9b\x1e\x87\xe9\xce\x55\x28\xdf"
    "\x8c\xa1\x89\x0d\xbf\xe6\x42\x68\x41\x99\x2d\x0f\xb0\x54\xbb\x16"
    [i]&255;
    unsigned s2=s1<<1;
    if (s2>=0x100) s2^=0x11b;
    unsigned s3=s1^s2;
    Te0[i]=s2<<24|s1<<16|s1<<8|s3;
    Te1[i]=s3<<24|s2<<16|s1<<8|s1;
    Te2[i]=s1<<24|s3<<16|s2<<8|s1;
    Te3[i]=s1<<24|s1<<16|s3<<8|s2;
    Te4[i]=s1<<24|s1<<16|s1<<8|s1;
  }

  // setup the forward key
  Nr = 10 + ((keylen/8)-2)*2;  // 10, 12, or 14 rounds
  int i = 0;
  U32* rk = &ek[0];
  U32 temp;
  static const U32 rcon[10] = {
    0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
    0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
    0x1B000000UL, 0x36000000UL};  // round constants

  LOAD32H(rk[0], key   );
  LOAD32H(rk[1], key +  4);
  LOAD32H(rk[2], key +  8);
  LOAD32H(rk[3], key + 12);
  if (keylen == 16) {
    for (;;) {
      temp  = rk[3];
      rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
      rk[5] = rk[1] ^ rk[4];
      rk[6] = rk[2] ^ rk[5];
      rk[7] = rk[3] ^ rk[6];
      if (++i == 10) {
         break;
      }
      rk += 4;
    }
  }
  else if (keylen == 24) {
    LOAD32H(rk[4], key + 16);
    LOAD32H(rk[5], key + 20);
    for (;;) {
      temp = rk[5];
      rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
      rk[ 7] = rk[ 1] ^ rk[ 6];
      rk[ 8] = rk[ 2] ^ rk[ 7];
      rk[ 9] = rk[ 3] ^ rk[ 8];
      if (++i == 8) {
        break;
      }
      rk[10] = rk[ 4] ^ rk[ 9];
      rk[11] = rk[ 5] ^ rk[10];
      rk += 6;
    }
  }
  else if (keylen == 32) {
    LOAD32H(rk[4], key + 16);
    LOAD32H(rk[5], key + 20);
    LOAD32H(rk[6], key + 24);
    LOAD32H(rk[7], key + 28);
    for (;;) {
      temp = rk[7];
      rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
      rk[ 9] = rk[ 1] ^ rk[ 8];
      rk[10] = rk[ 2] ^ rk[ 9];
      rk[11] = rk[ 3] ^ rk[10];
      if (++i == 7) {
        break;
      }
      temp = rk[11];
      rk[12] = rk[ 4] ^ setup_mix(temp<<24|temp>>8);
      rk[13] = rk[ 5] ^ rk[12];
      rk[14] = rk[ 6] ^ rk[13];
      rk[15] = rk[ 7] ^ rk[14];
      rk += 8;
    }
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %rbx
andq $0x0, 0x14f4(%rdi)
testq %rcx, %rcx
je 0x862b
movq %rcx, %r15
leaq 0x14f8(%rbx), %r12
leaq 0x14f4(%rbx), %rdi
movq %rcx, %rsi
callq 0x8aaf
addq $0x4, %r15
movq %r12, %rdi
movq %r15, %rsi
callq 0x8aaf
xorl %eax, %eax
leaq 0x1637c(%rip), %rcx     # 0x1e9b0
cmpq $0x100, %rax            # imm = 0x100
je 0x86e3
movzbl (%rax,%rcx), %esi
leal (%rsi,%rsi), %edi
movl %edi, %edx
xorl $0x11b, %edx            # imm = 0x11B
testb %sil, %sil
cmovnsl %edi, %edx
movl %edx, %edi
xorl %esi, %edi
movl %edx, %r10d
shll $0x18, %r10d
movl %esi, %r9d
shll $0x10, %r9d
orl %r9d, %r10d
movl %esi, %r8d
shll $0x8, %r8d
orl %r8d, %r10d
orl %edi, %r10d
movl %r10d, (%rbx,%rax,4)
movl %edi, %r10d
shll $0x18, %r10d
movl %edx, %r11d
shll $0x10, %r11d
orl %r10d, %r11d
orl %esi, %r11d
orl %r8d, %r11d
movl %r11d, 0x400(%rbx,%rax,4)
movl %edi, %r10d
shll $0x10, %r10d
movl %edx, %r11d
shll $0x8, %r11d
orl %r10d, %r11d
orl %esi, %r11d
orl %esi, %r8d
shll $0x18, %esi
orl %esi, %r11d
movl %r11d, 0x800(%rbx,%rax,4)
orl %r9d, %esi
shll $0x8, %edi
orl %esi, %edx
orl %edi, %edx
movl %edx, 0xc00(%rbx,%rax,4)
orl %esi, %r8d
movl %r8d, 0x1000(%rbx,%rax,4)
incq %rax
jmp 0x8634
pushq $0x8
popq %rcx
movl %ebp, %eax
cltd
idivl %ecx
leal 0x6(,%rax,2), %eax
movl %eax, 0x14f0(%rbx)
leaq 0x1400(%rbx), %rdi
movq %r14, %rsi
callq 0x8aaf
leaq 0x1404(%rbx), %rdi
leaq 0x4(%r14), %rsi
callq 0x8aaf
leaq 0x1408(%rbx), %rdi
leaq 0x8(%r14), %rsi
callq 0x8aaf
leaq 0x140c(%rbx), %rdi
leaq 0xc(%r14), %rsi
callq 0x8aaf
cmpl $0x20, %ebp
je 0x8906
cmpl $0x18, %ebp
je 0x881d
cmpl $0x10, %ebp
jne 0x8814
movl 0x1400(%rbx), %eax
xorl %ecx, %ecx
movl $0xff, %edx
leaq 0x1635a(%rip), %rsi     # 0x1eac0
movl 0x140c(%rbx,%rcx,4), %edi
movl %edi, %r8d
shrl $0xe, %r8d
andl $0x3fc, %r8d            # imm = 0x3FC
movzbl 0x1003(%rbx,%r8), %r8d
shll $0x18, %r8d
movl %edi, %r9d
shrl $0x8, %r9d
andl %edx, %r9d
movzbl 0x1002(%rbx,%r9,4), %r9d
shll $0x10, %r9d
orl %r8d, %r9d
movl %edi, %r8d
andl %edx, %r8d
movzbl 0x1001(%rbx,%r8,4), %r8d
shll $0x8, %r8d
orl %r9d, %r8d
movl %edi, %r9d
shrl $0x18, %r9d
movzbl 0x1000(%rbx,%r9,4), %r9d
orl %r8d, %r9d
xorl (%rcx,%rsi), %eax
xorl %r9d, %eax
movl %eax, 0x1410(%rbx,%rcx,4)
movl 0x1404(%rbx,%rcx,4), %r8d
xorl %eax, %r8d
movl %r8d, 0x1414(%rbx,%rcx,4)
xorl 0x1408(%rbx,%rcx,4), %r8d
movl %r8d, 0x1418(%rbx,%rcx,4)
xorl %edi, %r8d
movl %r8d, 0x141c(%rbx,%rcx,4)
addq $0x4, %rcx
cmpq $0x28, %rcx
jne 0x8766
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1410(%rbx), %rdi
leaq 0x10(%r14), %rsi
callq 0x8aaf
leaq 0x1414(%rbx), %rdi
addq $0x14, %r14
movq %r14, %rsi
callq 0x8aaf
movl 0x1400(%rbx), %eax
leaq 0x142c(%rbx), %rcx
xorl %edx, %edx
movl $0xff, %esi
leaq 0x16265(%rip), %rdi     # 0x1eac0
movl -0x18(%rcx), %r8d
movl %r8d, %r9d
shrl $0xe, %r9d
andl $0x3fc, %r9d            # imm = 0x3FC
movzbl 0x1003(%rbx,%r9), %r9d
shll $0x18, %r9d
movl %r8d, %r10d
shrl $0x8, %r10d
andl %esi, %r10d
movzbl 0x1002(%rbx,%r10,4), %r10d
shll $0x10, %r10d
orl %r9d, %r10d
movl %r8d, %r9d
andl %esi, %r9d
movzbl 0x1001(%rbx,%r9,4), %r9d
shll $0x8, %r9d
orl %r10d, %r9d
movl %r8d, %r10d
shrl $0x18, %r10d
movzbl 0x1000(%rbx,%r10,4), %r10d
orl %r9d, %r10d
xorl (%rdx,%rdi), %eax
xorl %r10d, %eax
movl %eax, -0x14(%rcx)
movl -0x28(%rcx), %r9d
xorl %eax, %r9d
movl %r9d, -0x10(%rcx)
xorl -0x24(%rcx), %r9d
movl %r9d, -0xc(%rcx)
xorl -0x20(%rcx), %r9d
movl %r9d, -0x8(%rcx)
cmpq $0x1c, %rdx
je 0x8814
xorl -0x1c(%rcx), %r9d
movl %r9d, -0x4(%rcx)
xorl %r8d, %r9d
movl %r9d, (%rcx)
addq $0x4, %rdx
addq $0x18, %rcx
jmp 0x885b
leaq 0x1410(%rbx), %rdi
leaq 0x10(%r14), %rsi
callq 0x8aaf
leaq 0x1414(%rbx), %rdi
leaq 0x14(%r14), %rsi
callq 0x8aaf
leaq 0x1418(%rbx), %rdi
leaq 0x18(%r14), %rsi
callq 0x8aaf
leaq 0x141c(%rbx), %rdi
addq $0x1c, %r14
movq %r14, %rsi
callq 0x8aaf
movl 0x1400(%rbx), %eax
xorl %ecx, %ecx
movl $0xff, %edx
leaq 0x16163(%rip), %rsi     # 0x1eac0
movl 0x141c(%rbx,%rcx,8), %edi
movl %edi, %r8d
shrl $0xe, %r8d
andl $0x3fc, %r8d            # imm = 0x3FC
movzbl 0x1003(%rbx,%r8), %r8d
shll $0x18, %r8d
movl %edi, %r9d
shrl $0x8, %r9d
andl %edx, %r9d
movzbl 0x1002(%rbx,%r9,4), %r9d
shll $0x10, %r9d
orl %r8d, %r9d
movl %edi, %r8d
andl %edx, %r8d
movzbl 0x1001(%rbx,%r8,4), %r8d
shll $0x8, %r8d
orl %r9d, %r8d
movl %edi, %r9d
shrl $0x18, %r9d
movzbl 0x1000(%rbx,%r9,4), %r9d
orl %r8d, %r9d
xorl (%rcx,%rsi), %eax
xorl %r9d, %eax
movl %eax, 0x1420(%rbx,%rcx,8)
movl 0x1404(%rbx,%rcx,8), %r8d
xorl %eax, %r8d
movl %r8d, 0x1424(%rbx,%rcx,8)
xorl 0x1408(%rbx,%rcx,8), %r8d
movl %r8d, 0x1428(%rbx,%rcx,8)
xorl 0x140c(%rbx,%rcx,8), %r8d
movl %r8d, 0x142c(%rbx,%rcx,8)
cmpq $0x18, %rcx
je 0x8814
roll $0x18, %r8d
movl %r8d, %r9d
shrl $0xe, %r9d
andl $0x3fc, %r9d            # imm = 0x3FC
movzbl 0x1003(%rbx,%r9), %r9d
shll $0x18, %r9d
movl %r8d, %r10d
shrl $0x8, %r10d
andl %edx, %r10d
movzbl 0x1002(%rbx,%r10,4), %r10d
shll $0x10, %r10d
orl %r9d, %r10d
movl %r8d, %r9d
andl %edx, %r9d
movzbl 0x1001(%rbx,%r9,4), %r9d
shll $0x8, %r9d
orl %r10d, %r9d
shrl $0x18, %r8d
movzbl 0x1000(%rbx,%r8,4), %r8d
orl %r9d, %r8d
xorl 0x1410(%rbx,%rcx,8), %r8d
movl %r8d, 0x1430(%rbx,%rcx,8)
xorl 0x1414(%rbx,%rcx,8), %r8d
movl %r8d, 0x1434(%rbx,%rcx,8)
xorl 0x1418(%rbx,%rcx,8), %r8d
movl %r8d, 0x1438(%rbx,%rcx,8)
xorl %edi, %r8d
movl %r8d, 0x143c(%rbx,%rcx,8)
addq $0x4, %rcx
jmp 0x895d