// File: /workspace/github_c_makefile_star2_O3/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 0x2f1055
movq %rdx, %rbx
testq %rdx, %rdx
je 0x2f1055
movq %rcx, %rax
movq %rdi, %r14
movq %rsi, %rcx
shrq $0x3, %rcx
movq %rax, %rdi
shrq $0x3, %rdi
movl %esi, %edx
andl $0x7, %edx
addq %rcx, %r14
addq %rdi, %rbx
andl $0x7, %eax
cmpl %eax, %edx
jne 0x2f0de1
testl %edx, %edx
je 0x2f0f8a
movl $0x8, %eax
subl %edx, %eax
movq %r8, %r12
subq %rax, %r12
jae 0x2f1003
andl $0x7, %esi
addl %esi, %r8d
movb $0x8, %cl
subb %r8b, %cl
movzbl (%rbx), %eax
movzbl (%r14), %edx
xorl %eax, %edx
shrl %cl, %edx
shll %cl, %edx
xorl %eax, %edx
movb %dl, (%rbx)
jmp 0x2f105a
testq %r8, %r8
je 0x2f0f8f
xorl %r11d, %r11d
movl $0x8, %r15d
xorl %r10d, %r10d
xorl %esi, %esi
movl %edx, %ecx
orl %eax, %ecx
je 0x2f0f97
testl %edx, %edx
je 0x2f0e27
movl $0x8, %r9d
subl %edx, %r9d
movl %esi, %ecx
movl $0x40, %edi
subq %rcx, %rdi
cmpq %r9, %r8
jbe 0x2f0e2b
cmpq %r9, %rdi
cmovaeq %r9, %rdi
jmp 0x2f0e32
xorl %edx, %edx
jmp 0x2f0e6d
cmpq %rdi, %r8
cmovbq %r8, %rdi
subl %edi, %r9d
movq $-0x1, %r12
movl %edi, %ecx
shlq %cl, %r12
shlq %cl, %r10
movzbl (%r14), %r13d
movl %r9d, %ecx
shrl %cl, %r13d
notl %r12d
andl %r12d, %r13d
orq %r13, %r10
subq %rdi, %r8
addl %edi, %esi
addl %edi, %edx
xorl %ecx, %ecx
cmpl $0x8, %edx
sete %cl
cmovel %r11d, %edx
addq %rcx, %r14
testl %eax, %eax
je 0x2f0f7d
movl %esi, %ecx
leaq (%r8,%rcx), %rdi
movl $0x8, %r9d
subl %eax, %r9d
cmpq %r9, %rdi
cmovael %r9d, %edi
cmpq $0x8, %r8
jb 0x2f0ec3
addq $-0x41, %rcx
cmpq $-0xa, %rcx
ja 0x2f0ec3
movq %r10, %rcx
shlq $0x8, %rcx
movzbl (%r14), %r10d
incq %r14
orq %rcx, %r10
addq $-0x8, %r8
addl $0x8, %esi
cmpq $0x8, %r8
jb 0x2f0ec3
leaq -0x41(%rsi), %rcx
cmpq $-0x9, %rcx
jb 0x2f0e9b
cmpl %esi, %edi
jbe 0x2f0f0b
movzbl (%r14), %r12d
movl %esi, %ecx
movl $0x40, %edx
subq %rcx, %rdx
cmpq %r8, %rdx
cmovaeq %r8, %rdx
cmpq $0x8, %rdx
cmovaeq %r15, %rdx
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl %edx, %ecx
shll %cl, %ebp
notl %ebp
shlq %cl, %r10
movb $0x8, %cl
subb %dl, %cl
movq %r12, %r13
shrq %cl, %r13
andl %ebp, %r13d
orq %r13, %r10
subq %rdx, %r8
addl %edx, %esi
cmpl %edi, %esi
jb 0x2f0ecb
movq $-0x1, %r12
movl %edi, %ecx
shlq %cl, %r12
subl %edi, %r9d
notq %r12
movq %r12, %r13
movl %r9d, %ecx
shlq %cl, %r13
subl %edi, %esi
movq %r10, %rbp
movl %esi, %ecx
shrq %cl, %rbp
andl %r12d, %ebp
movzbl (%rbx), %r12d
movl %r9d, %ecx
shlq %cl, %rbp
notl %r13d
andl %r12d, %r13d
orl %r13d, %ebp
movb %bpl, (%rbx)
addl %edi, %eax
xorl %edi, %edi
cmpl $0x8, %eax
sete %dil
cmovel %r11d, %eax
addq %rbx, %rdi
cmpl $0x8, %esi
jb 0x2f0f78
addq $-0x8, %rsi
movq %r10, %r9
movl %esi, %ecx
shrq %cl, %r9
movb %r9b, (%rdi)
incq %rdi
cmpq $0x7, %rsi
ja 0x2f0f60
movq %rdi, %rbx
jmp 0x2f0f7f
xorl %eax, %eax
testq %r8, %r8
jne 0x2f0df8
jmp 0x2f0f94
movq %r8, %r12
jmp 0x2f100e
xorl %esi, %esi
xorl %r10d, %r10d
xorl %r8d, %r8d
cmpq $0x8, %r8
setae %dil
jb 0x2f0fd9
movl %esi, %ecx
addq $-0x41, %rcx
cmpq $-0xa, %rcx
ja 0x2f0fd9
movq %r10, %rcx
shlq $0x8, %rcx
movzbl (%r14), %r10d
incq %r14
orq %rcx, %r10
addl $0x8, %esi
addq $-0x8, %r8
cmpq $0x8, %r8
setae %dil
jb 0x2f0fd9
leaq -0x41(%rsi), %rcx
cmpq $-0x9, %rcx
jb 0x2f0fad
cmpl $0x8, %esi
jb 0x2f0ff8
movl %esi, %esi
addq $-0x8, %rsi
movq %r10, %r9
movl %esi, %ecx
shrq %cl, %r9
movb %r9b, (%rbx)
incq %rbx
cmpq $0x7, %rsi
ja 0x2f0fe0
testb %dil, %dil
jne 0x2f0f97
testl %esi, %esi
je 0x2f106b
jmp 0x2f1070
movb (%r14), %al
movb %al, (%rbx)
incq %r14
incq %rbx
testq %r12, %r12
je 0x2f105a
movq %r12, %r15
shrq $0x3, %r15
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x17660
andq $0x7, %r12
je 0x2f105a
movb $0x8, %cl
subb %r12b, %cl
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
shll %cl, %eax
movzbl (%r14,%r15), %ecx
andl %eax, %ecx
notl %eax
movzbl (%rbx,%r15), %edx
orl $0x1, %eax
andl %edx, %eax
orl %eax, %ecx
movb %cl, (%rbx,%r15)
jmp 0x2f105a
callq 0x8710e
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %esi, %esi
testq %r8, %r8
je 0x2f105a
testq %r8, %r8
je 0x2f10ef
movq %r14, %r11
movl %esi, %ecx
movl $0x8, %r9d
subl %edx, %r9d
movl $0x40, %edi
subq %rcx, %rdi
cmpq %r9, %r8
jae 0x2f1099
cmpq %rdi, %r8
cmovbq %r8, %rdi
jmp 0x2f10a0
cmpq %r9, %rdi
cmovaeq %r9, %rdi
movq $-0x1, %r14
movl %edi, %ecx
shlq %cl, %r14
movq %r10, %r15
shlq %cl, %r15
subl %edi, %r9d
notl %r14d
movzbl (%r11), %r10d
movl %r9d, %ecx
shrl %cl, %r10d
andl %r14d, %r10d
orq %r15, %r10
addl %edi, %esi
movl %edx, %ecx
addl %edi, %ecx
xorl %edx, %edx
xorl %r14d, %r14d
cmpl $0x8, %ecx
sete %r14b
cmovnel %ecx, %edx
addq %r11, %r14
subq %rdi, %r8
je 0x2f1159
movq %r14, %r11
cmpl $0x40, %esi
jb 0x2f1078
jmp 0x2f1159
xorl %r8d, %r8d
jmp 0x2f1159
movl $0x8, %edi
subl %eax, %edi
cmpl %edi, %esi
cmovbl %esi, %edi
movq $-0x1, %r11
movl %edi, %ecx
shlq %cl, %r11
addl %edi, %eax
notl %r11d
movb $0x8, %r9b
subb %al, %r9b
movl %r9d, %ecx
shlq %cl, %r11
subl %edi, %esi
movq %r10, %r15
movl %esi, %ecx
shrq %cl, %r15
movl %r9d, %ecx
shlq %cl, %r15
cmpl $0x8, %edi
movzbl (%rbx), %ecx
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
cmovnel %r11d, %edi
xorl %ecx, %r15d
andl %edi, %r15d
xorl %ecx, %r15d
movb %r15b, (%rbx)
xorl %ecx, %ecx
xorl %edi, %edi
cmpl $0x8, %eax
sete %dil
cmovel %ecx, %eax
addq %rdi, %rbx
testl %esi, %esi
jne 0x2f10f4
jmp 0x2f1069