// File: /workspace/github_c_makefile_star2_O1/genometools[P]genometools/src/core/bitpackstringop.c
// Function: gt_bsCopy
void
gt_bsCopy(constBitString src, BitOffset offsetSrc,
       BitString dest, BitOffset offsetDest, BitOffset numBits)
{
  size_t elemStartSrc = offsetSrc/bitElemBits,
    elemStartDest = offsetDest/bitElemBits;
  unsigned bitTopSrc = offsetSrc%bitElemBits,
    bitTopDest = offsetDest%bitElemBits;
  BitOffset bitsLeft = numBits;
  const BitElem *p = src + elemStartSrc;
  BitElem *q = dest + elemStartDest;
  gt_assert(src && dest);
  /* special optimization if equally aligned data will be copied */
  if (bitTopSrc == bitTopDest)
  {
    if (bitTopSrc)
    {
      BitElem mask = (~(BitElem)0) >> bitTopSrc;
      if (numBits < bitElemBits - bitTopSrc)
      {
        unsigned backShift = bitElemBits - numBits - bitTopSrc;
        mask &= ~(BitElem)0 << backShift;
        *q = (*q & ~mask) | (*p & mask);
        /* TODO: try wether  r = a ^ ((a ^ b) & mask) is faster, see above */
        return;
      }
      else
      {
        *q = (*q & ~mask) | (*p & mask);
        ++p, ++q;
        bitsLeft -= bitElemBits - bitTopSrc;
      }
    }
    if (bitsLeft)
    {
      size_t completeElems = bitsLeft/bitElemBits;
      memcpy(q, p, completeElems);
      p += completeElems, q += completeElems;
      bitsLeft %= bitElemBits;
    }
    if (bitsLeft)
    {
      BitElem mask = (~(BitElem)0) << (bitElemBits - bitsLeft);
      *q = (*q & ~mask) | (*p & mask);
    }
  }
  else
  {
    GtUword accum = 0;
    unsigned bitsInAccum = 0;
    while (bitsLeft && (bitTopSrc || bitTopDest))
    {
      if (bitTopSrc)
      {
        GtUword mask;
        unsigned bits2Read = GT_MIN3(bitElemBits - bitTopSrc, bitsLeft,
                                  sizeof (accum) * CHAR_BIT - bitsInAccum);
        unsigned unreadRightBits = (bitElemBits - bitTopSrc - bits2Read);
        mask = (~((~(GtUword)0) << bits2Read));
        accum = (accum << bits2Read) | (((*p) >> unreadRightBits) & mask);
        bitsLeft -= bits2Read;
        bitsInAccum += bits2Read;
        if ((bitTopSrc += bits2Read) == bitElemBits)
          bitTopSrc = 0, ++p;
      }
      if (bitTopDest)
      {
        unsigned bits2Write = GT_MIN(bitsLeft + bitsInAccum,
                                  bitElemBits - bitTopDest);
        while (bitsLeft >= bitElemBits
               && sizeof (accum) * CHAR_BIT - bitsInAccum > bitElemBits)
        {
          accum = accum << bitElemBits | (*p++);
          bitsLeft -= bitElemBits;
          bitsInAccum += bitElemBits;
        }
        if (bits2Write > bitsInAccum)
        {
          /* very inconvinient: we have to take all the bits we can get
           * just to fill the first incomplete element */
          while (bitsInAccum < bits2Write)
          {
            GtUword mask;
            unsigned bits2Read = GT_MIN3(sizeof (accum) * CHAR_BIT
                                         - bitsInAccum, bitsLeft, bitElemBits);
            unsigned unreadRightBits = (bitElemBits - bits2Read);
            mask = (~((~(GtUword)0) << bits2Read)) << unreadRightBits;
            accum = (accum << bits2Read) | ((*p) & mask) >> unreadRightBits;
            bitsLeft -= bits2Read;
            bitsInAccum += bits2Read;
            bitTopSrc = bits2Read;
          }
        }
        /* accum holds enough bits to fill incomplete region at dest start */
        {
          unsigned unwrittenRightBits = bitElemBits
            - bitTopDest - bits2Write;
          GtUword mask =
            (~((~(GtUword)0) << bits2Write)) << unwrittenRightBits;
          *q = (*q & ~mask)
            | (((accum >> (bitsInAccum -= bits2Write))
                << unwrittenRightBits) & mask);
          if ((bitTopDest += bits2Write) == bitElemBits)
            ++q, bitTopDest = 0;
        }
        while (bitsInAccum >= bitElemBits)
        {
          *q++ = accum >> (bitsInAccum -= bitElemBits);
        }
      }
    }
    /* all reads and writes are aligned on BitElems in this loop */
    do
    {
      /* fill accumulator */
      while (bitsLeft >= bitElemBits
             && sizeof (accum) * CHAR_BIT - bitsInAccum > bitElemBits)
      {
        accum = accum << bitElemBits | (*p++);
        bitsInAccum += bitElemBits;
        bitsLeft -= bitElemBits;
      }
      /* write out accum */
      while (bitsInAccum >= bitElemBits)
      {
        *q++ = accum >> (bitsInAccum -= bitElemBits);
      }
    }
    while (bitsLeft >= bitElemBits);
    /* write remaining (trailing) bits */
    while (bitsLeft || bitsInAccum)
    {
      while (bitsLeft && bitsInAccum < sizeof (accum) * CHAR_BIT)
      {
        unsigned bits2Read = GT_MIN3(bitsLeft, bitElemBits - bitTopSrc,
                                  sizeof (accum) * CHAR_BIT - bitsInAccum);
        unsigned unreadRightBits = (bitElemBits - bitTopSrc - bits2Read);
        GtUword mask =
          ~((~(GtUword)0) << bits2Read);
        accum = (accum << bits2Read) | (((*p) >> unreadRightBits) & mask);
        bitsLeft -= bits2Read;
        bitsInAccum += bits2Read;
        if ((bitTopSrc += bits2Read) == bitElemBits)
          ++p, bitTopSrc = 0;
      }
      while (bitsInAccum)
      {
        unsigned bits2Write = GT_MIN(bitsInAccum, bitElemBits - bitTopDest),
          unwrittenRightBits = bitElemBits - bits2Write - bitTopDest;
        GtUword mask = (~(GtUword)0);
        if (bits2Write != bitElemBits)
        {
          mask = (~(mask << bits2Write)) << unwrittenRightBits;
        }
        *q = (*q & ~mask) |
            (((accum >> (bitsInAccum -= bits2Write))
              << unwrittenRightBits) & mask);
        if ((bitTopDest += bits2Write) == bitElemBits)
          bitTopDest = 0, ++q;
      }
    }
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x2fa3f3
movq %rdx, %r15
testq %rdx, %rdx
je 0x2fa3f3
movq %r8, %rbx
movq %rcx, %r8
movq %rdi, %r14
movq %rsi, %rcx
shrq $0x3, %rcx
movq %r8, %rdx
shrq $0x3, %rdx
movl %esi, %eax
andl $0x7, %eax
addq %rcx, %r14
addq %rdx, %r15
andl $0x7, %r8d
cmpl %r8d, %eax
jne 0x2fa15a
testl %eax, %eax
je 0x2fa3a7
movl $0x8, %edx
subl %eax, %edx
movq %rbx, %rax
subq %rdx, %rax
jae 0x2fa393
andl $0x7, %esi
leal (%rbx,%rsi), %eax
movb $0x8, %cl
subb %al, %cl
movzbl (%r15), %eax
movzbl (%r14), %esi
xorl %eax, %esi
shrl %cl, %esi
shll %cl, %esi
xorl %eax, %esi
movb %sil, (%r15)
movq %rbx, %rax
jmp 0x2fa39f
testq %rbx, %rbx
je 0x2fa31a
xorl %r13d, %r13d
movl $0x8, %r11d
movl %r8d, %ebp
movq %r15, %r12
xorl %r9d, %r9d
xorl %edx, %edx
movl %eax, %ecx
orl %ebp, %ecx
je 0x2fa321
xorl %r8d, %r8d
testl %eax, %eax
je 0x2fa1a7
movl $0x8, %edi
subl %eax, %edi
movl %edx, %ecx
movl $0x40, %esi
subq %rcx, %rsi
cmpq %rdi, %rbx
jbe 0x2fa1ab
cmpq %rdi, %rsi
cmovaeq %rdi, %rsi
jmp 0x2fa1b2
xorl %eax, %eax
jmp 0x2fa1f4
cmpq %rsi, %rbx
cmovbq %rbx, %rsi
subl %esi, %edi
movl %esi, %r15d
movq $-0x1, %r13
movl %esi, %ecx
shlq %cl, %r13
shlq %cl, %r9
movzbl (%r14), %r10d
movl %edi, %ecx
shrl %cl, %r10d
notl %r13d
andl %r13d, %r10d
orq %r10, %r9
subq %r15, %rbx
addl %esi, %edx
addl %esi, %eax
xorl %ecx, %ecx
cmpl $0x8, %eax
sete %cl
movl $0x0, %r13d
cmovel %r13d, %eax
addq %rcx, %r14
testl %ebp, %ebp
je 0x2fa306
movl %edx, %ecx
leaq (%rbx,%rcx), %rsi
movl $0x8, %edi
subl %ebp, %edi
cmpq %rdi, %rsi
cmovael %edi, %esi
cmpq $0x8, %rbx
jb 0x2fa247
addq $-0x41, %rcx
cmpq $-0xa, %rcx
ja 0x2fa247
movq %r9, %rcx
shlq $0x8, %rcx
movzbl (%r14), %r9d
incq %r14
orq %rcx, %r9
addq $-0x8, %rbx
addl $0x8, %edx
cmpq $0x8, %rbx
jb 0x2fa247
leaq -0x41(%rdx), %rcx
cmpq $-0x9, %rcx
jb 0x2fa21f
cmpl %edx, %esi
jbe 0x2fa292
movzbl (%r14), %r8d
movl %edx, %ecx
movl $0x40, %eax
subq %rcx, %rax
cmpq %rbx, %rax
cmovaeq %rbx, %rax
cmpq $0x8, %rax
cmovaeq %r11, %rax
movl $0xffffffff, %r10d      # imm = 0xFFFFFFFF
movl %eax, %ecx
shll %cl, %r10d
notl %r10d
shlq %cl, %r9
movb $0x8, %cl
subb %al, %cl
movq %r8, %r15
shrq %cl, %r15
andl %r10d, %r15d
orq %r15, %r9
subq %rax, %rbx
addl %eax, %edx
cmpl %esi, %edx
jb 0x2fa24f
movq $-0x1, %r8
movl %esi, %ecx
shlq %cl, %r8
subl %esi, %edi
notq %r8
movq %r8, %r10
movl %edi, %ecx
shlq %cl, %r10
subl %esi, %edx
movq %r9, %r15
movl %edx, %ecx
shrq %cl, %r15
andl %r8d, %r15d
movzbl (%r12), %r8d
notl %r10d
movl %edi, %ecx
shlq %cl, %r15
andl %r8d, %r10d
orl %r10d, %r15d
movb %r15b, (%r12)
addl %esi, %ebp
xorl %r15d, %r15d
cmpl $0x8, %ebp
sete %r15b
movl %ebp, %r8d
cmovel %r13d, %r8d
addq %r12, %r15
cmpl $0x8, %edx
jb 0x2fa309
movl %edx, %edx
addq $-0x8, %rdx
movq %r9, %rsi
movl %edx, %ecx
shrq %cl, %rsi
movb %sil, (%r15)
incq %r15
cmpq $0x7, %rdx
ja 0x2fa2ec
jmp 0x2fa309
movq %r12, %r15
movl %r8d, %ebp
movq %r15, %r12
testq %rbx, %rbx
jne 0x2fa177
jmp 0x2fa327
xorl %edx, %edx
xorl %r9d, %r9d
jmp 0x2fa327
movq %r12, %r15
movl %ebp, %r8d
cmpq $0x8, %rbx
setae %sil
jb 0x2fa369
movl %edx, %ecx
addq $-0x41, %rcx
cmpq $-0xa, %rcx
ja 0x2fa369
movq %r9, %rcx
shlq $0x8, %rcx
movzbl (%r14), %r9d
incq %r14
orq %rcx, %r9
addl $0x8, %edx
addq $-0x8, %rbx
cmpq $0x8, %rbx
setae %sil
jb 0x2fa369
leaq -0x41(%rdx), %rcx
cmpq $-0x9, %rcx
jb 0x2fa33d
cmpl $0x8, %edx
jb 0x2fa388
movl %edx, %edx
addq $-0x8, %rdx
movq %r9, %rdi
movl %edx, %ecx
shrq %cl, %rdi
movb %dil, (%r15)
incq %r15
cmpq $0x7, %rdx
ja 0x2fa370
testb %sil, %sil
jne 0x2fa327
testl %edx, %edx
je 0x2fa409
jmp 0x2fa40e
movb (%r14), %cl
movb %cl, (%r15)
incq %r14
incq %r15
cmpq %rdx, %rbx
movq %rax, %rbx
jb 0x2fa3f8
testq %rbx, %rbx
je 0x2fa3cc
movq %rbx, %r12
shrq $0x3, %r12
movq %r15, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x17660
addq %r12, %r14
addq %r12, %r15
andl $0x7, %ebx
jmp 0x2fa3ce
xorl %ebx, %ebx
testq %rbx, %rbx
je 0x2fa3f8
movb $0x8, %cl
subb %bl, %cl
movzbl (%r15), %eax
movl $0xfe, %edx
shrl %cl, %edx
shll %cl, %edx
movzbl (%r14), %ecx
xorl %eax, %ecx
andl %edx, %ecx
xorl %eax, %ecx
movb %cl, (%r15)
jmp 0x2fa3f8
callq 0x88e3d
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %edx, %edx
testq %rbx, %rbx
je 0x2fa3f8
testq %rbx, %rbx
je 0x2fa501
movq %r14, %r10
cmpl $0x3f, %edx
ja 0x2fa501
movl %edx, %ecx
movl $0x8, %edi
subl %eax, %edi
movl $0x40, %esi
subq %rcx, %rsi
cmpq %rdi, %rbx
jae 0x2fa442
cmpq %rsi, %rbx
cmovbq %rbx, %rsi
jmp 0x2fa449
cmpq %rdi, %rsi
cmovaeq %rdi, %rsi
subl %esi, %edi
movq $-0x1, %r11
movl %esi, %ecx
shlq %cl, %r11
movq %r9, %r14
shlq %cl, %r14
movl %esi, %r12d
notl %r11d
movzbl (%r10), %r9d
movl %edi, %ecx
shrl %cl, %r9d
andl %r11d, %r9d
orq %r14, %r9
addl %esi, %edx
movl %eax, %ecx
addl %esi, %ecx
xorl %eax, %eax
xorl %r14d, %r14d
cmpl $0x8, %ecx
sete %r14b
cmovnel %ecx, %eax
addq %r10, %r14
subq %r12, %rbx
je 0x2fa501
movq %r14, %r10
cmpl $0x40, %edx
jb 0x2fa423
jmp 0x2fa501
movl $0x8, %esi
subl %r8d, %esi
cmpl %esi, %edx
cmovbl %edx, %esi
movq $-0x1, %r10
movl %esi, %ecx
shlq %cl, %r10
addl %esi, %r8d
notl %r10d
movb $0x8, %dil
subb %r8b, %dil
movl %edi, %ecx
shlq %cl, %r10
subl %esi, %edx
movq %r9, %r11
movl %edx, %ecx
shrq %cl, %r11
movl %edi, %ecx
shlq %cl, %r11
cmpl $0x8, %esi
movzbl (%r15), %ecx
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
cmovnel %r10d, %esi
xorl %ecx, %r11d
andl %esi, %r11d
xorl %ecx, %r11d
movb %r11b, (%r15)
xorl %ecx, %ecx
xorl %esi, %esi
cmpl $0x8, %r8d
sete %sil
cmovel %ecx, %r8d
addq %rsi, %r15
testl %edx, %edx
jne 0x2fa499
jmp 0x2fa407