// File: /workspace/github_c_makefile_star2_O3/genometools[P]genometools/src/core/bitpackstringop64.c
// Function: gt_bsStoreNonUniformUInt64Array
void
gt_bsStoreNonUniformUInt64Array(
  BitString str, BitOffset offset, GT_UNUSED size_t numValues,
  BitOffset totalBitsLeft, unsigned numBitsList[], const uint64_t val[])
{
  /* idea: read as much as possible from val in each iteration,
   * accumulate if bitsInAccum < bitElemBits */
  size_t j = 0;
  unsigned bitTop = offset%bitElemBits,
    bitsLeft; /*< how many bits in currentVal == val[j] are left */
  BitElem *p = str + offset/bitElemBits;
  unsigned bitsInAccum;
  GtUint64 accum, valMask = ~(GtUint64)0, currentVal;
  gt_assert(numBitsList != NULL);
  gt_assert(val != NULL);
  gt_assert(numValues != 0);
  if (numBitsList[0] < (sizeof (val[0])*CHAR_BIT))
    valMask = ~(valMask << numBitsList[0]);
  gt_assert(str && val);
  gt_assert(numBitsList[0] <= sizeof (val[0])*CHAR_BIT);
  /* user requested zero values, ugly but must be handled, since legal */
  if (!totalBitsLeft)
  {
    return;
  }
  accum = val[0] & valMask;
  totalBitsLeft -= bitsInAccum = numBitsList[0];
  if (totalBitsLeft)
  {
    unsigned numBits = numBitsList[++j];
    gt_assert(numBits <= sizeof (val[0])*CHAR_BIT);
    valMask = (numBits < 64)?
      ~((~(uint64_t)0) << numBits):~(uint64_t)0;
    currentVal = val[j] & valMask;
    totalBitsLeft -= bitsLeft = numBits;
  }
  else
  {
    currentVal = 0;
    bitsLeft = 0;
  }
  /* set bits of first element if not aligned */
  if (bitTop)
  {
    BitElem mask = ~(~(GtUint64)0 << (bitElemBits - bitTop));
    while ((totalBitsLeft || bitsLeft) && bitsInAccum < bitElemBits - bitTop)
    {
      unsigned bits2Read, bitsFree = sizeof (accum)*CHAR_BIT - bitsInAccum;

      if ((bits2Read = GT_MIN(bitsFree, bitsLeft)) < sizeof (accum)*CHAR_BIT)
      {
        accum = accum << bits2Read
          | ((currentVal) >> (bitsLeft - bits2Read));
      }
      else
        accum = currentVal;

      /* all of val[j] consumed? */
      bitsInAccum += bits2Read;
      if (!(bitsLeft -= bits2Read) && totalBitsLeft)
      {
        unsigned numBits = numBitsList[++j];
        gt_assert(numBits <= sizeof (val[0])*CHAR_BIT);
        valMask = (numBits < 64)?
          ~((~(uint64_t)0) << numBits):~(uint64_t)0;
        currentVal = val[j] & valMask, totalBitsLeft -= bitsLeft = numBits;
      }
    }
    /* at this point accum holds as many bits as we could get
     * to fill the first BitElem in str, but did we get enough? */
    if (bitsInAccum < bitElemBits - bitTop)
    {
      /* no there's not enough */
      unsigned backShift = bitElemBits - bitsInAccum - bitTop;
      mask &= ~(GtUint64)0 << backShift;
      *p = (*p & ~mask) | ((accum << backShift) & mask);
      /* TODO: try wether  r = a ^ ((a ^ b) & mask) is faster, see below */
      return; /* if we couldn't gather more bits, there's none left */
    }
    else
    {
      /* yep, just or with accumVals */
      *p = (*p & ~mask) | (accum >> (bitsInAccum - bitElemBits + bitTop));
      ++p;
      bitsInAccum -= bitElemBits - bitTop;
    }
  }

  while (totalBitsLeft || (bitsInAccum + bitsLeft) > bitElemBits)
  {
    while ((totalBitsLeft || bitsLeft)
          && ((bitsInAccum < bitElemBits)
              || (bitsLeft < sizeof (accum)*CHAR_BIT - bitsInAccum)))
    {
      unsigned bits2Read, bitsFree = sizeof (accum)*CHAR_BIT - bitsInAccum;
      if ((bits2Read = GT_MIN(bitsFree, bitsLeft)) < sizeof (accum)*CHAR_BIT)
      {
        GtUint64 mask = ~((~(GtUint64)0) << bits2Read);
        accum = accum << bits2Read
          | ((currentVal >> (bitsLeft - bits2Read)) & mask);
      }
      else
        accum = currentVal;
      bitsInAccum += bits2Read;
      /* all of currentVal == val[j] consumed? */
      if (bits2Read == bitsLeft && totalBitsLeft)
      {
        unsigned numBits = numBitsList[++j];
        gt_assert(numBits <= sizeof (val[0])*CHAR_BIT);
        valMask = (numBits < 64)?
          ~((~(uint64_t)0) << numBits):~(uint64_t)0;
        currentVal = val[j] & valMask, totalBitsLeft -= bitsLeft = numBits;
      }
      else
        bitsLeft -= bits2Read;
    }
    /* now we have enough bits in accum */
    while (bitsInAccum >= bitElemBits)
    {
      *p++ = accum >> (bitsInAccum - bitElemBits);
      bitsInAccum -= bitElemBits;
    }
  }
  /* write the rest bits left in accum and currentVal */
  accum = (accum << bitsLeft)
    | (currentVal & (valMask >> (numBitsList[j] - bitsLeft)));
  bitsInAccum += bitsLeft;
  while (bitsInAccum >= bitElemBits)
  {
    *p++ = accum >> (bitsInAccum - bitElemBits);
    bitsInAccum -= bitElemBits;
  }
  if (bitsInAccum)
  {
    GtUint64 mask =
      ~(GtUint64)0 << (bitElemBits - bitsInAccum);
    *p = (*p & ~mask) | ((accum << (bitElemBits - bitsInAccum))& mask);
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %r8, (%rsp)
testq %r8, %r8
je 0x2f44d1
testq %r9, %r9
je 0x2f44d6
testq %rdx, %rdx
je 0x2f44db
movq %rcx, %rax
movq (%rsp), %rcx
movl (%rcx), %edx
movq $-0x1, %r8
movq $-0x1, %r14
movl %edx, %ecx
shlq %cl, %r14
cmpq $0x40, %rdx
notq %r14
cmovaeq %r8, %r14
testq %rdi, %rdi
je 0x2f44e0
cmpl $0x41, %edx
jae 0x2f44e5
testq %rax, %rax
je 0x2f44b8
movq (%r9), %r15
andq %r14, %r15
cmpq %rax, %rdx
jne 0x2f41a8
movq %r9, %r8
xorl %r12d, %r12d
xorl %r10d, %r10d
xorl %r9d, %r9d
xorl %eax, %eax
jmp 0x2f41f2
movq (%rsp), %rcx
movl 0x4(%rcx), %r10d
cmpq $0x41, %r10
jae 0x2f44ea
movq $-0x1, %r14
movl %r10d, %ecx
shlq %cl, %r14
movq $-0x1, %rcx
cmpl $0x40, %r10d
notq %r14
cmoveq %rcx, %r14
movq %r9, %r8
movq 0x8(%r9), %r12
andq %r14, %r12
movq %rdx, %rcx
addq %r10, %rcx
subq %rcx, %rax
movl $0x1, %r9d
movl %esi, %ebp
andl $0x7, %ebp
movq %rsi, %rcx
shrq $0x3, %rcx
addq %rcx, %rdi
testl %ebp, %ebp
je 0x2f4463
movq %rsi, 0x10(%rsp)
movl $0x8, %r11d
subl %ebp, %r11d
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl %r11d, %ecx
shll %cl, %esi
movl %esi, 0xc(%rsp)
testq %rax, %rax
setne %sil
testl %r10d, %r10d
setne %bl
orb %sil, %bl
cmpl %r11d, %edx
setb %cl
andb %cl, %bl
cmpb $0x1, %bl
jne 0x2f42e1
movl $0x40, %ebx
subl %edx, %ebx
cmpl %r10d, %ebx
cmovael %r10d, %ebx
movl %ebx, %ecx
shlq %cl, %r15
subl %ebx, %r10d
movq %r12, %r13
movl %r10d, %ecx
shrq %cl, %r13
orq %r13, %r15
cmpl $0x40, %ebx
cmovaeq %r12, %r15
testl %r10d, %r10d
jne 0x2f42ba
testb $0x1, %sil
je 0x2f42ba
movq (%rsp), %rcx
movl 0x4(%rcx,%r9,4), %r10d
cmpq $0x41, %r10
jae 0x2f44cc
movq $-0x1, %r14
movl %r10d, %ecx
shlq %cl, %r14
cmpl $0x40, %r10d
notq %r14
movq $-0x1, %rcx
cmoveq %rcx, %r14
movq 0x8(%r8,%r9,8), %r12
incq %r9
andq %r14, %r12
subq %r10, %rax
addl %ebx, %edx
testq %rax, %rax
setne %sil
sete %bl
testl %r10d, %r10d
sete %r13b
cmpl %r11d, %edx
setb %cl
testb %bl, %r13b
jne 0x2f42e1
cmpl %r11d, %edx
jb 0x2f4246
testb %cl, %cl
je 0x2f431f
addl %edx, %ebp
movb $0x8, %cl
subb %bpl, %cl
movq $-0x1, %rax
shlq %cl, %rax
movl 0xc(%rsp), %edx
notl %edx
orl $0xff01, %edx           # imm = 0xFF01
movzwl %dx, %edx
andl %edx, %eax
movzbl (%rdi), %esi
notl %eax
shlq %cl, %r15
andl %esi, %eax
andl %edx, %r15d
orl %eax, %r15d
movq %r15, %r14
jmp 0x2f44b5
movzbl (%rdi), %ecx
movl 0xc(%rsp), %ebx
andl %ecx, %ebx
movq 0x10(%rsp), %rcx
orl $0xf8, %ecx
addl %edx, %ecx
movq %r15, %rsi
shrq %cl, %rsi
orl %ebx, %esi
movb %sil, (%rdi)
incq %rdi
subl %r11d, %edx
jmp 0x2f4463
testq %rax, %rax
setne %bl
jne 0x2f4362
testl %r10d, %r10d
jne 0x2f4362
movq %r15, %r11
movl %edx, %esi
jmp 0x2f4433
cmpl $0x8, %edx
setb %cl
movl %r10d, %esi
movl %edx, %r11d
movl $0x40, %ebp
subq %r11, %rbp
cmpq %rsi, %rbp
seta %sil
orb %cl, %sil
cmpb $0x1, %sil
jne 0x2f4442
cmpl %ebp, %r10d
movl %ebp, %esi
cmovbl %r10d, %esi
movq %r12, %r11
cmpl $0x3f, %esi
ja 0x2f43be
movq $-0x1, %r13
movl %esi, %ecx
shlq %cl, %r13
shlq %cl, %r15
movl %r10d, %ecx
subl %esi, %ecx
movq %r12, %r11
shrq %cl, %r11
notq %r13
andq %r13, %r11
orq %r15, %r11
cmpl %ebp, %r10d
seta %cl
notb %bl
orb %cl, %bl
testb $0x1, %bl
jne 0x2f440f
movq (%rsp), %rcx
movl 0x4(%rcx,%r9,4), %r10d
cmpq $0x41, %r10
jae 0x2f44c7
movq $-0x1, %rbx
movq $-0x1, %r14
movl %r10d, %ecx
shlq %cl, %r14
cmpl $0x40, %r10d
notq %r14
cmoveq %rbx, %r14
movq 0x8(%r8,%r9,8), %r12
incq %r9
andq %r14, %r12
subq %r10, %rax
jmp 0x2f4412
subl %esi, %r10d
addl %edx, %esi
movl %esi, %edx
movq %r11, %r15
testq %rax, %rax
setne %bl
jne 0x2f4362
movl %esi, %edx
movq %r11, %r15
testl %r10d, %r10d
jne 0x2f4362
xorl %eax, %eax
xorl %r10d, %r10d
cmpl $0x8, %esi
jb 0x2f445e
movl %esi, %edx
movq %r11, %r15
movl %edx, %edx
addq $-0x8, %rdx
movq %r15, %rsi
movl %edx, %ecx
shrq %cl, %rsi
movb %sil, (%rdi)
incq %rdi
cmpq $0x7, %rdx
ja 0x2f4444
jmp 0x2f4463
movq %r11, %r15
movl %esi, %edx
testq %rax, %rax
jne 0x2f434b
leal (%r10,%rdx), %esi
cmpl $0x9, %esi
jae 0x2f434b
movl %r10d, %ecx
shlq %cl, %r15
movq (%rsp), %rax
movl (%rax,%r9,4), %ecx
subl %r10d, %ecx
shrq %cl, %r14
andq %r12, %r14
orq %r15, %r14
cmpl $0x7, %esi
ja 0x2f44b5
testl %esi, %esi
je 0x2f44b8
movb $0x8, %cl
subb %sil, %cl
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
shll %cl, %eax
movzbl (%rdi), %edx
notl %eax
andl %edx, %eax
shlq %cl, %r14
orq %rax, %r14
movb %r14b, (%rdi)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x880fe
callq 0x880c5
callq 0x881e2
callq 0x881a9
callq 0x88170
callq 0x88137
callq 0x88053
callq 0x8808c