// File: /workspace/github_cpp_makefile_star2_O3/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:
movq $0x0, 0x14f4(%rdi)
testq %rcx, %rcx
je 0x896d
movl (%rcx), %eax
bswapl %eax
movl %eax, 0x14f4(%rdi)
movl 0x4(%rcx), %eax
bswapl %eax
movl %eax, 0x14f8(%rdi)
xorl %eax, %eax
leaq 0x2d7da(%rip), %rcx     # 0x36150
pxor %xmm0, %xmm0
movdqa 0x2c92e(%rip), %xmm1    # 0x352b0
movd (%rax,%rcx), %xmm4
movdqa %xmm4, %xmm2
punpcklbw %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7]
pxor %xmm5, %xmm5
punpcklwd %xmm2, %xmm5    # xmm5 = xmm5[0],xmm2[0],xmm5[1],xmm2[1],xmm5[2],xmm2[2],xmm5[3],xmm2[3]
punpcklwd %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3]
movdqa %xmm2, %xmm3
paddd %xmm2, %xmm3
punpcklbw %xmm4, %xmm4    # xmm4 = xmm4[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
punpcklwd %xmm4, %xmm4    # xmm4 = xmm4[0,0,1,1,2,2,3,3]
pxor %xmm6, %xmm6
pcmpgtb %xmm4, %xmm6
movdqa %xmm6, %xmm4
pandn %xmm3, %xmm4
pxor %xmm1, %xmm3
pand %xmm6, %xmm3
por %xmm4, %xmm3
movdqa %xmm3, %xmm6
pxor %xmm2, %xmm6
movdqa %xmm3, %xmm7
pslld $0x18, %xmm7
movdqa %xmm2, %xmm4
pslld $0x8, %xmm4
movdqa %xmm6, %xmm8
pslld $0x10, %xmm8
movdqa %xmm3, %xmm9
pslld $0x8, %xmm9
por %xmm2, %xmm9
por %xmm8, %xmm9
movdqa %xmm2, %xmm8
pslld $0x18, %xmm8
por %xmm8, %xmm9
por %xmm5, %xmm8
por %xmm4, %xmm5
por %xmm7, %xmm5
por %xmm6, %xmm5
movdqu %xmm5, (%rdi,%rax,4)
movdqa %xmm6, %xmm5
pslld $0x18, %xmm5
movdqa %xmm3, %xmm7
pslld $0x10, %xmm7
por %xmm2, %xmm7
por %xmm5, %xmm7
por %xmm4, %xmm7
movdqu %xmm7, 0x400(%rdi,%rax,4)
movdqu %xmm9, 0x800(%rdi,%rax,4)
pslld $0x8, %xmm6
por %xmm8, %xmm3
por %xmm6, %xmm3
movdqu %xmm3, 0xc00(%rdi,%rax,4)
por %xmm2, %xmm4
por %xmm8, %xmm4
movdqu %xmm4, 0x1000(%rdi,%rax,4)
addq $0x4, %rax
cmpq $0x100, %rax            # imm = 0x100
jne 0x8982
leal 0x7(%rdx), %eax
testl %edx, %edx
cmovnsl %edx, %eax
sarl $0x3, %eax
leal 0x6(,%rax,2), %eax
movl %eax, 0x14f0(%rdi)
movl (%rsi), %eax
bswapl %eax
movl %eax, 0x1400(%rdi)
movl 0x4(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x1404(%rdi)
movl 0x8(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x1408(%rdi)
movl 0xc(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x140c(%rdi)
cmpl $0x20, %edx
je 0x8c84
cmpl $0x18, %edx
je 0x8bad
cmpl $0x10, %edx
jne 0x8bac
xorl %ecx, %ecx
movl $0xff, %edx
leaq 0x2d763(%rip), %rsi     # 0x36260
movl 0x140c(%rdi,%rcx,4), %r8d
movl %r8d, %r9d
shrl $0xe, %r9d
andl $0x3fc, %r9d            # imm = 0x3FC
movzbl 0x1003(%rdi,%r9), %r9d
shll $0x18, %r9d
movl %r8d, %r10d
shrl $0x8, %r10d
andl %edx, %r10d
movzbl 0x1002(%rdi,%r10,4), %r10d
shll $0x10, %r10d
orl %r9d, %r10d
movl %r8d, %r9d
andl %edx, %r9d
movzbl 0x1001(%rdi,%r9,4), %r9d
shll $0x8, %r9d
orl %r10d, %r9d
movl %r8d, %r10d
shrl $0x18, %r10d
movzbl 0x1000(%rdi,%r10,4), %r10d
orl %r9d, %r10d
xorl (%rcx,%rsi), %eax
xorl %r10d, %eax
movl %eax, 0x1410(%rdi,%rcx,4)
movl 0x1404(%rdi,%rcx,4), %r9d
xorl %eax, %r9d
movl %r9d, 0x1414(%rdi,%rcx,4)
xorl 0x1408(%rdi,%rcx,4), %r9d
movl %r9d, 0x1418(%rdi,%rcx,4)
xorl %r8d, %r9d
movl %r9d, 0x141c(%rdi,%rcx,4)
addq $0x4, %rcx
cmpq $0x28, %rcx
jne 0x8afd
retq
movl 0x10(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x1410(%rdi)
movl 0x14(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x1414(%rdi)
leaq 0x142c(%rdi), %rcx
xorl %edx, %edx
movl $0xff, %esi
leaq 0x2d688(%rip), %r8      # 0x36260
movl -0x18(%rcx), %r9d
movl %r9d, %r10d
shrl $0xe, %r10d
andl $0x3fc, %r10d           # imm = 0x3FC
movzbl 0x1003(%rdi,%r10), %r10d
shll $0x18, %r10d
movl %r9d, %r11d
shrl $0x8, %r11d
andl %esi, %r11d
movzbl 0x1002(%rdi,%r11,4), %r11d
shll $0x10, %r11d
orl %r10d, %r11d
movl %r9d, %r10d
andl %esi, %r10d
movzbl 0x1001(%rdi,%r10,4), %r10d
shll $0x8, %r10d
orl %r11d, %r10d
movl %r9d, %r11d
shrl $0x18, %r11d
movzbl 0x1000(%rdi,%r11,4), %r11d
orl %r10d, %r11d
xorl (%rdx,%r8), %eax
xorl %r11d, %eax
movl %eax, -0x14(%rcx)
movl -0x28(%rcx), %r10d
xorl %eax, %r10d
movl %r10d, -0x10(%rcx)
xorl -0x24(%rcx), %r10d
movl %r10d, -0xc(%rcx)
xorl -0x20(%rcx), %r10d
movl %r10d, -0x8(%rcx)
cmpq $0x1c, %rdx
je 0x8bac
xorl -0x1c(%rcx), %r10d
movl %r10d, -0x4(%rcx)
xorl %r9d, %r10d
movl %r10d, (%rcx)
addq $0x4, %rdx
addq $0x18, %rcx
jmp 0x8bd8
movl 0x10(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x1410(%rdi)
movl 0x14(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x1414(%rdi)
movl 0x18(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x1418(%rdi)
movl 0x1c(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x141c(%rdi)
xorl %ecx, %ecx
movl $0xff, %edx
leaq 0x2d5a2(%rip), %rsi     # 0x36260
movl 0x141c(%rdi,%rcx,8), %r8d
movl %r8d, %r9d
shrl $0xe, %r9d
andl $0x3fc, %r9d            # imm = 0x3FC
movzbl 0x1003(%rdi,%r9), %r9d
shll $0x18, %r9d
movl %r8d, %r10d
shrl $0x8, %r10d
andl %edx, %r10d
movzbl 0x1002(%rdi,%r10,4), %r10d
shll $0x10, %r10d
orl %r9d, %r10d
movl %r8d, %r9d
andl %edx, %r9d
movzbl 0x1001(%rdi,%r9,4), %r9d
shll $0x8, %r9d
orl %r10d, %r9d
movl %r8d, %r10d
shrl $0x18, %r10d
movzbl 0x1000(%rdi,%r10,4), %r10d
orl %r9d, %r10d
xorl (%rcx,%rsi), %eax
xorl %r10d, %eax
movl %eax, 0x1420(%rdi,%rcx,8)
movl 0x1404(%rdi,%rcx,8), %r9d
xorl %eax, %r9d
movl %r9d, 0x1424(%rdi,%rcx,8)
xorl 0x1408(%rdi,%rcx,8), %r9d
movl %r9d, 0x1428(%rdi,%rcx,8)
xorl 0x140c(%rdi,%rcx,8), %r9d
movl %r9d, 0x142c(%rdi,%rcx,8)
cmpq $0x18, %rcx
je 0x8bac
roll $0x18, %r9d
movl %r9d, %r10d
shrl $0xe, %r10d
andl $0x3fc, %r10d           # imm = 0x3FC
movzbl 0x1003(%rdi,%r10), %r10d
shll $0x18, %r10d
movl %r9d, %r11d
shrl $0x8, %r11d
andl %edx, %r11d
movzbl 0x1002(%rdi,%r11,4), %r11d
shll $0x10, %r11d
orl %r10d, %r11d
movl %r9d, %r10d
andl %edx, %r10d
movzbl 0x1001(%rdi,%r10,4), %r10d
shll $0x8, %r10d
orl %r11d, %r10d
shrl $0x18, %r9d
movzbl 0x1000(%rdi,%r9,4), %r9d
orl %r10d, %r9d
xorl 0x1410(%rdi,%rcx,8), %r9d
movl %r9d, 0x1430(%rdi,%rcx,8)
xorl 0x1414(%rdi,%rcx,8), %r9d
movl %r9d, 0x1434(%rdi,%rcx,8)
xorl 0x1418(%rdi,%rcx,8), %r9d
movl %r9d, 0x1438(%rdi,%rcx,8)
xorl %r8d, %r9d
movl %r9d, 0x143c(%rdi,%rcx,8)
addq $0x4, %rcx
jmp 0x8cbe
nop