// File: /workspace/github_c_makefile_star2_O0/mjosaarinen[P]brutus/crypto_aead/scream10v3/sse/tae.c
// Function: crypto_aead_encrypt
int crypto_aead_encrypt(unsigned char *c,unsigned long long *clen,
                        const unsigned char *m,unsigned long long mlen,
                        const unsigned char *ad,unsigned long long adlen,
                        const unsigned char *nsec,
                        const unsigned char *npub,
                        const unsigned char *k) {
    
  v16qi data[16];
  uint8_t buffer[16*16] = {0};
  v16qi tweakey[16*TWEAKEY_SIZE];
  uint8_t pad[16];

  v16qi *checksum = (v16qi*) &buffer[ 16 * (((mlen+15)/16)%16) ];
  v16qi auth = CV(0);

  // Associated Data
  if (adlen > 0) {
    size_t idx=0;
    tweakey_schedule(k, npub, TWEAK_AD, tweakey);
    
    for (idx=0; idx+256<adlen; idx+=16*16) {
      read128(ad+idx, data);
      encrypt_tweakey(data, tweakey);
      tweakey_increment(tweakey, idx);
      write128_checksum(data, NULL, &auth, 16);
    }

    // Final chunk
    uint8_t buffer2[16*16] = {0};
    memcpy(buffer2, ad+idx, adlen-idx);
    if ((adlen % 16) == 0) {
      tweakey_set(tweakey, (adlen-idx-1)/16, 15, TWEAK_AD_LAST_FULL);
    } else {
      tweakey_set(tweakey, (adlen-idx-1)/16, 15, TWEAK_AD_LAST_PARTIAL);
      buffer2[adlen-idx] = 0x80;
    }
    read128(buffer2, data);
    encrypt_tweakey(data, tweakey);
    write128_checksum(data, NULL, &auth, (adlen-idx+15)/16);
  }

  size_t idx=0;
  tweakey_schedule(k, npub, TWEAK_MESSAGE, tweakey);
  if (mlen > 0) {
    
    for (idx=0; idx+16*16<=mlen; idx+=16*16) {
      read128_with_checksum(m+idx, data, checksum, 16);
      encrypt_tweakey(data, tweakey);
      tweakey_increment(tweakey, idx);
      write128(data, c+idx);
    }

    // Final chunk(s)
    if (mlen > idx+240) {
      /* printf ("## Almost!\n"); */
      // Almost full chunk: one extra chunk for checksum
      uint8_t buffer2[16*16] = {0};
      memcpy(buffer2, m+idx, 240);

      memset(buffer2+256-16, 0, 16);
      buffer2[255] = 8*(mlen%16);
      read128_with_checksum(buffer2, data, checksum, 15);
      update_checksum(m+idx+240, checksum, mlen-idx-240);

      encrypt_tweakey(data, tweakey);
      tweakey_increment(tweakey, idx);
      write128(data, buffer2);
      memcpy(c+idx, buffer2, 240);
      memcpy(pad,   buffer2+240, mlen%16);
      idx = mlen;
    } else {
      // Partial chunk: encrypt length for final block; checksum included
      memcpy(buffer, m+idx, mlen-idx);
      update_checksum(buffer, checksum, mlen-idx);

      if ((mlen % 16) != 0) {
	// Encrypt partial block length
	memset(&buffer[((mlen-idx)|15)-15], 0, 16);
	buffer[(mlen-idx)|15] = 8*(mlen%16);
      }
    }
  }

  // Tag generation
  tweakey_set(tweakey, ((mlen-idx+15)/16), 15, 2*8*mlen+1);
  tweakey_set(tweakey, ((mlen-idx+15)/16), 14, mlen>>4);
  tweakey_set(tweakey, ((mlen-idx+15)/16), 13, mlen>>12);
  tweakey_set(tweakey, ((mlen-idx+15)/16), 12, mlen>>20);
  tweakey_set(tweakey, ((mlen-idx+15)/16), 11, mlen>>28);
  read128(buffer, data);
  encrypt_tweakey(data, tweakey);
  write128(data, buffer);

  memcpy(c+idx, buffer, (mlen-idx)&(~15));
  memcpy(pad,   buffer+((mlen-idx)&(~15)), (mlen-idx)%16);

  *checksum ^= auth;

  memcpy(c+mlen, checksum, CRYPTO_ABYTES);

  unsigned i;
  for (i=0; i < mlen%16; i++)
    c[16*(mlen/16)+i] = m[16*(mlen/16)+i] ^ pad[i];

  *clen = mlen+CRYPTO_ABYTES;

  return 0;
}

// Assembly:
subq $0x9b8, %rsp            # imm = 0x9B8
movq 0x9d0(%rsp), %rax
movq 0x9c8(%rsp), %rax
movq 0x9c0(%rsp), %rax
movq %rdi, 0x9b0(%rsp)
movq %rsi, 0x9a8(%rsp)
movq %rdx, 0x9a0(%rsp)
movq %rcx, 0x998(%rsp)
movq %r8, 0x990(%rsp)
movq %r9, 0x988(%rsp)
vpxor %xmm0, %xmm0, %xmm0
vmovups %ymm0, (%rsp)
vmovdqu %ymm0, 0x860(%rsp)
vmovdqu %ymm0, 0x840(%rsp)
vmovdqu %ymm0, 0x820(%rsp)
vmovdqu %ymm0, 0x800(%rsp)
vmovdqu %ymm0, 0x7e0(%rsp)
vmovdqu %ymm0, 0x7c0(%rsp)
vmovdqu %ymm0, 0x7a0(%rsp)
vmovdqu %ymm0, 0x780(%rsp)
movl 0x998(%rsp), %eax
addl $0xf, %eax
andl $0xf0, %eax
leaq 0x780(%rsp,%rax), %rax
movq %rax, 0x268(%rsp)
vpxor %xmm0, %xmm0, %xmm0
vmovdqa %xmm0, 0x250(%rsp)
cmpq $0x0, 0x988(%rsp)
jbe 0x62c0
movq $0x0, 0x248(%rsp)
movq 0x9d0(%rsp), %rdi
movq 0x9c8(%rsp), %rsi
leaq 0x280(%rsp), %rcx
movl $0x2, %edx
vzeroupper
callq 0x10c0
movq $0x0, 0x248(%rsp)
movq 0x248(%rsp), %rax
addq $0x100, %rax            # imm = 0x100
cmpq 0x988(%rsp), %rax
jae 0x6194
movq 0x990(%rsp), %rdi
addq 0x248(%rsp), %rdi
leaq 0x880(%rsp), %rsi
callq 0x10f0
leaq 0x880(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x1110
leaq 0x280(%rsp), %rdi
movq 0x248(%rsp), %rsi
callq 0x1050
leaq 0x880(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
leaq 0x250(%rsp), %rdx
movl $0x10, %ecx
callq 0x1040
movq 0x248(%rsp), %rax
addq $0x100, %rax            # imm = 0x100
movq %rax, 0x248(%rsp)
jmp 0x60f8
leaq 0x140(%rsp), %rdi
xorl %esi, %esi
movl $0x100, %edx            # imm = 0x100
callq 0x1030
leaq 0x140(%rsp), %rdi
movq 0x990(%rsp), %rsi
addq 0x248(%rsp), %rsi
movq 0x988(%rsp), %rdx
subq 0x248(%rsp), %rdx
callq 0x1130
movq 0x988(%rsp), %rax
andq $0xf, %rax
cmpq $0x0, %rax
jne 0x621a
leaq 0x280(%rsp), %rdi
movq 0x988(%rsp), %rax
subq 0x248(%rsp), %rax
subq $0x1, %rax
shrq $0x4, %rax
movl %eax, %esi
movl $0xf, %edx
movl $0x4, %ecx
callq 0x1060
jmp 0x6263
leaq 0x280(%rsp), %rdi
movq 0x988(%rsp), %rax
subq 0x248(%rsp), %rax
subq $0x1, %rax
shrq $0x4, %rax
movl %eax, %esi
movl $0xf, %edx
movl $0x6, %ecx
callq 0x1060
movq 0x988(%rsp), %rax
subq 0x248(%rsp), %rax
movb $-0x80, 0x140(%rsp,%rax)
leaq 0x140(%rsp), %rdi
leaq 0x880(%rsp), %rsi
callq 0x10f0
leaq 0x880(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x1110
leaq 0x880(%rsp), %rdi
movq 0x988(%rsp), %rax
subq 0x248(%rsp), %rax
addq $0xf, %rax
shrq $0x4, %rax
movl %eax, %ecx
xorl %eax, %eax
movl %eax, %esi
leaq 0x250(%rsp), %rdx
callq 0x1040
movq $0x0, 0x138(%rsp)
movq 0x9d0(%rsp), %rdi
movq 0x9c8(%rsp), %rsi
leaq 0x280(%rsp), %rcx
xorl %edx, %edx
vzeroupper
callq 0x10c0
cmpq $0x0, 0x998(%rsp)
jbe 0x65e7
movq $0x0, 0x138(%rsp)
movq 0x138(%rsp), %rax
addq $0x100, %rax            # imm = 0x100
cmpq 0x998(%rsp), %rax
ja 0x63b1
movq 0x9a0(%rsp), %rdi
addq 0x138(%rsp), %rdi
leaq 0x880(%rsp), %rsi
movq 0x268(%rsp), %rdx
movl $0x10, %ecx
callq 0x1120
leaq 0x880(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x1110
leaq 0x280(%rsp), %rdi
movq 0x138(%rsp), %rsi
callq 0x1050
leaq 0x880(%rsp), %rdi
movq 0x9b0(%rsp), %rsi
addq 0x138(%rsp), %rsi
callq 0x1070
movq 0x138(%rsp), %rax
addq $0x100, %rax            # imm = 0x100
movq %rax, 0x138(%rsp)
jmp 0x6309
movq 0x998(%rsp), %rax
movq 0x138(%rsp), %rcx
addq $0xf0, %rcx
cmpq %rcx, %rax
jbe 0x6523
leaq 0x30(%rsp), %rdi
xorl %esi, %esi
movl $0x100, %edx            # imm = 0x100
callq 0x1030
leaq 0x30(%rsp), %rdi
movq 0x9a0(%rsp), %rsi
addq 0x138(%rsp), %rsi
movl $0xf0, %edx
callq 0x1130
leaq 0x30(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
addq $-0x10, %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1030
movq 0x998(%rsp), %rax
andq $0xf, %rax
shlq $0x3, %rax
movb %al, 0x12f(%rsp)
leaq 0x30(%rsp), %rdi
leaq 0x880(%rsp), %rsi
movq 0x268(%rsp), %rdx
movl $0xf, %ecx
callq 0x1120
movq 0x9a0(%rsp), %rdi
addq 0x138(%rsp), %rdi
addq $0xf0, %rdi
movq 0x268(%rsp), %rsi
movq 0x998(%rsp), %rdx
subq 0x138(%rsp), %rdx
subq $0xf0, %rdx
callq 0x1100
leaq 0x880(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x1110
leaq 0x280(%rsp), %rdi
movq 0x138(%rsp), %rsi
callq 0x1050
leaq 0x880(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x1070
movq 0x9b0(%rsp), %rdi
addq 0x138(%rsp), %rdi
leaq 0x30(%rsp), %rsi
movl $0xf0, %edx
callq 0x1130
leaq 0x270(%rsp), %rdi
leaq 0x30(%rsp), %rsi
addq $0xf0, %rsi
movq 0x998(%rsp), %rdx
andq $0xf, %rdx
callq 0x1130
movq 0x998(%rsp), %rax
movq %rax, 0x138(%rsp)
jmp 0x65e5
leaq 0x780(%rsp), %rdi
movq 0x9a0(%rsp), %rsi
addq 0x138(%rsp), %rsi
movq 0x998(%rsp), %rdx
subq 0x138(%rsp), %rdx
callq 0x1130
leaq 0x780(%rsp), %rdi
movq 0x268(%rsp), %rsi
movq 0x998(%rsp), %rdx
subq 0x138(%rsp), %rdx
callq 0x1100
movq 0x998(%rsp), %rax
andq $0xf, %rax
cmpq $0x0, %rax
je 0x65e3
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
orq $0xf, %rax
subq $0xf, %rax
leaq 0x780(%rsp), %rdi
addq %rax, %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1030
movq 0x998(%rsp), %rax
andq $0xf, %rax
shlq $0x3, %rax
movb %al, %cl
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
orq $0xf, %rax
movb %cl, 0x780(%rsp,%rax)
jmp 0x65e5
jmp 0x65e7
leaq 0x280(%rsp), %rdi
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
addq $0xf, %rax
shrq $0x4, %rax
movl %eax, %esi
movq 0x998(%rsp), %rax
shlq $0x4, %rax
addq $0x1, %rax
movl $0xf, %edx
movzbl %al, %ecx
callq 0x1060
leaq 0x280(%rsp), %rdi
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
addq $0xf, %rax
shrq $0x4, %rax
movl %eax, %esi
movq 0x998(%rsp), %rax
shrq $0x4, %rax
movl $0xe, %edx
movzbl %al, %ecx
callq 0x1060
leaq 0x280(%rsp), %rdi
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
addq $0xf, %rax
shrq $0x4, %rax
movl %eax, %esi
movq 0x998(%rsp), %rax
shrq $0xc, %rax
movl $0xd, %edx
movzbl %al, %ecx
callq 0x1060
leaq 0x280(%rsp), %rdi
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
addq $0xf, %rax
shrq $0x4, %rax
movl %eax, %esi
movq 0x998(%rsp), %rax
shrq $0x14, %rax
movl $0xc, %edx
movzbl %al, %ecx
callq 0x1060
leaq 0x280(%rsp), %rdi
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
addq $0xf, %rax
shrq $0x4, %rax
movl %eax, %esi
movq 0x998(%rsp), %rax
shrq $0x1c, %rax
movl $0xb, %edx
movzbl %al, %ecx
callq 0x1060
leaq 0x780(%rsp), %rdi
leaq 0x880(%rsp), %rsi
callq 0x10f0
leaq 0x880(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x1110
leaq 0x880(%rsp), %rdi
leaq 0x780(%rsp), %rsi
callq 0x1070
movq 0x9b0(%rsp), %rdi
addq 0x138(%rsp), %rdi
leaq 0x780(%rsp), %rsi
movq 0x998(%rsp), %rdx
subq 0x138(%rsp), %rdx
andq $-0x10, %rdx
callq 0x1130
leaq 0x270(%rsp), %rdi
leaq 0x780(%rsp), %rsi
movq 0x998(%rsp), %rax
subq 0x138(%rsp), %rax
andq $-0x10, %rax
addq %rax, %rsi
movq 0x998(%rsp), %rdx
subq 0x138(%rsp), %rdx
andq $0xf, %rdx
callq 0x1130
vmovdqa 0x250(%rsp), %xmm0
movq 0x268(%rsp), %rax
vpxor (%rax), %xmm0, %xmm0
vmovdqa %xmm0, (%rax)
movq 0x9b0(%rsp), %rax
movq 0x998(%rsp), %rcx
movq 0x268(%rsp), %rdx
movq (%rdx), %rsi
movq %rsi, (%rax,%rcx)
movq 0x8(%rdx), %rdx
movq %rdx, 0x8(%rax,%rcx)
movl $0x0, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
movq 0x998(%rsp), %rcx
andq $0xf, %rcx
cmpq %rcx, %rax
jae 0x6882
movq 0x9a0(%rsp), %rax
movq 0x998(%rsp), %rcx
shrq $0x4, %rcx
shlq $0x4, %rcx
movl 0x2c(%rsp), %edx
addq %rdx, %rcx
movzbl (%rax,%rcx), %eax
movl 0x2c(%rsp), %ecx
movzbl 0x270(%rsp,%rcx), %ecx
xorl %ecx, %eax
movb %al, %dl
movq 0x9b0(%rsp), %rax
movq 0x998(%rsp), %rcx
shrq $0x4, %rcx
shlq $0x4, %rcx
movl 0x2c(%rsp), %esi
addq %rsi, %rcx
movb %dl, (%rax,%rcx)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x680b
movq 0x998(%rsp), %rcx
addq $0x10, %rcx
movq 0x9a8(%rsp), %rax
movq %rcx, (%rax)
xorl %eax, %eax
addq $0x9b8, %rsp            # imm = 0x9B8
retq
nopw %cs:(%rax,%rax)