// File: /workspace/github_c_makefile_star2_O2/heltilda[P]cicada/lnklst.c
// Function: copyElements
ccInt copyElements(linkedlist *sourceList, ccInt sourceBegin, linkedlist *destList, ccInt destBegin, ccInt numberToCopy)
{
    ccInt firstCopied, lastCopied, sourceBottom, destBottom, elementSize;
    sublistHeader *currentSourceSublist, *currentDestSublist;
    
    
        // First, make sure the user is within range.
    
    if ((sourceList->memory == NULL) || (destList->memory == NULL))  return init_err;
    if (sourceList->elementSize != destList->elementSize)  return mismatched_indices_err;
    if (numberToCopy == 0)  return passed;            // put before el-exists-check, since if NTC == 0 we often can't pass a valid element
    if ((!elementExists(sourceList, sourceBegin)) || (!elementExists(destList, destBegin)))  return out_of_range_err;
    if ((!elementExists(sourceList, sourceBegin + numberToCopy - 1)) || (!elementExists(destList, destBegin+numberToCopy-1)))
        return out_of_range_err;
    
    elementSize = sourceList->elementSize;
    
    
        // Now start copying the lists.  If we can do it from lowest to highest without overwriting, that's easiest (first clause of 'if' statement).
        // Either way, we iteratively hop down sublists: updating them, restricting the size of the copied memory block, and copying the memory.
    
    if ((sourceBegin > destBegin) || (sourceBegin+numberToCopy <= destBegin) || (sourceList != destList))
    {
        currentSourceSublist = findSublist(sourceList, sourceBegin, &sourceBottom);
        currentDestSublist = findSublist(destList, destBegin, &destBottom);
        firstCopied = 1;
        lastCopied = numberToCopy - 1;
        while (lastCopied < numberToCopy)
        {
            if (currentSourceSublist->numElements+sourceBottom-1 < sourceBegin+firstCopied-1)   {    //update sublists
                sourceBottom = sourceBottom + currentSourceSublist->numElements;
                currentSourceSublist = currentSourceSublist->nextSublist;       }
            
            if (currentDestSublist->numElements+destBottom-1 < destBegin+firstCopied-1)   {
                destBottom = destBottom + currentDestSublist->numElements;
                currentDestSublist = currentDestSublist->nextSublist;     }
            
            lastCopied = numberToCopy;
            if (sourceBottom+currentSourceSublist->numElements < sourceBegin+lastCopied)      // restrict copy length
                lastCopied = sourceBottom + currentSourceSublist->numElements - sourceBegin;
            if (destBottom+currentDestSublist->numElements < destBegin+lastCopied)
                lastCopied = destBottom + currentDestSublist->numElements - destBegin;

            memmove((void *) (((char *) currentDestSublist) + (firstCopied+destBegin-destBottom-1)*elementSize + sublistHeaderSize),
                    (void *) (((char *) currentSourceSublist) + (firstCopied+sourceBegin-sourceBottom-1)*elementSize + sublistHeaderSize),
                    elementSize*(lastCopied-firstCopied+1));
            
            firstCopied = lastCopied+1;
    }   }
    
    else if (sourceBegin < destBegin)       // No, copy from the top down; otherwise we will overwrite something.
    {
        currentSourceSublist = findSublist(sourceList, sourceBegin+numberToCopy-1, &sourceBottom);
        currentDestSublist = findSublist(destList, destBegin+numberToCopy-1, &destBottom);
        firstCopied = numberToCopy+1;
        lastCopied = numberToCopy;
        
        while(firstCopied > 1)
        {
            firstCopied = 1;          // how much to copy?
            if (sourceBottom > firstCopied+sourceBegin-1)
                firstCopied = sourceBottom - sourceBegin + 1;
            if (destBottom > firstCopied+destBegin-1)
                firstCopied = destBottom - destBegin + 1;
            
                        // here we copy first, then scale the lists
            memmove((void *) ((char *) currentDestSublist + (firstCopied+destBegin-destBottom-1)*elementSize + sublistHeaderSize),
                    (void *) ((char *) currentSourceSublist + (firstCopied+sourceBegin-sourceBottom-1)*elementSize + sublistHeaderSize),
                    elementSize*(lastCopied-firstCopied+1));
            
            lastCopied = firstCopied-1;
            if (firstCopied == sourceBottom-sourceBegin+1)
                currentSourceSublist = findSublist(sourceList, sourceBegin+lastCopied-1, &sourceBottom);
            if (firstCopied == destBottom-destBegin+1)
                currentDestSublist = findSublist(destList, destBegin+lastCopied-1, &destBottom);
    }   }
    
    return passed;
}

// Assembly:
pushq $0x3
popq %rax
cmpq $0x0, 0x8(%rdi)
je 0x8b07
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, %r12
cmpq $0x0, 0x8(%rdx)
je 0x8af9
movq %rdi, %r13
movl 0x10(%rdi), %ebp
cmpl 0x10(%r12), %ebp
jne 0x89d9
movl %r8d, %r15d
testl %r8d, %r8d
je 0x8af7
movl %ecx, %ebx
movl %esi, %r14d
movl (%r13), %edx
cmpl %esi, %edx
setl %al
testl %esi, %esi
setle %cl
orb %al, %cl
pushq $0x2
popq %rax
jne 0x8af9
movl (%r12), %ecx
cmpl %ebx, %ecx
setl %sil
testl %ebx, %ebx
setle %dil
orb %sil, %dil
jne 0x8af9
leal (%r15,%r14), %edi
leal (%r15,%r14), %esi
decl %esi
cmpl %esi, %edx
setl %dl
movl %edi, 0x28(%rsp)
cmpl $0x2, %edi
setl %dil
orb %dl, %dil
jne 0x8af9
leal (%r15,%rbx), %edx
leal (%r15,%rbx), %edi
decl %edi
cmpl %edi, %ecx
setl %cl
cmpl $0x2, %edx
setl %dl
orb %cl, %dl
jne 0x8af9
cmpq %r12, %r13
jne 0x89e1
cmpl %ebx, %r14d
ja 0x89e1
cmpl %ebx, 0x28(%rsp)
jbe 0x89e1
cmpl %ebx, %r14d
jae 0x8af7
leaq 0x14(%rsp), %rdx
movl %edi, 0x8(%rsp)
movq %r13, %rdi
callq 0x83ba
movq %rax, 0x18(%rsp)
leaq 0x4(%rsp), %rdx
movq %r12, %rdi
movl 0x8(%rsp), %esi
callq 0x83ba
movq %rax, %rsi
incl %r15d
leal -0x1(%r14), %eax
movq %rax, 0x38(%rsp)
leal -0x1(%rbx), %eax
movl %eax, 0x30(%rsp)
movl 0x4(%rsp), %eax
movl %eax, %ecx
subl %ebx, %ecx
incl %ecx
movl %ecx, 0x20(%rsp)
movl %eax, 0x34(%rsp)
notl %eax
addl %ebx, %eax
movq %rax, 0x40(%rsp)
addq $0x18, %rsi
movl %r15d, %eax
movq %rsi, 0x28(%rsp)
cmpl $0x2, %eax
jl 0x8af7
movl 0x14(%rsp), %ecx
movl %ecx, %edx
subl %r14d, %edx
leal 0x1(%rdx), %edi
pushq $0x1
popq %rdx
movl %edx, %r15d
movl %edi, 0x8(%rsp)
cmovgl %edi, %r15d
leal (%r15,%rbx), %edx
cmpl %edx, 0x34(%rsp)
jl 0x8942
movl 0x20(%rsp), %edx
movl %edx, %r15d
movq 0x40(%rsp), %rdx
addl %r15d, %edx
imull %ebp, %edx
movslq %edx, %rdi
addq %rsi, %rdi
notl %ecx
addl %r14d, %ecx
addl %r15d, %ecx
imull %ebp, %ecx
movslq %ecx, %rcx
movq 0x18(%rsp), %rdx
leaq (%rdx,%rcx), %rsi
addq $0x18, %rsi
subl %r15d, %eax
imull %ebp, %eax
movslq %eax, %rdx
callq 0x8220
leal -0x1(%r15), %ecx
cmpl 0x8(%rsp), %r15d
jne 0x89ab
movq 0x38(%rsp), %rax
leal (%rax,%rcx), %esi
movq %r13, %rdi
leaq 0x14(%rsp), %rdx
movq %rcx, 0x8(%rsp)
callq 0x83ba
movq 0x8(%rsp), %rcx
movq %rax, 0x18(%rsp)
movl %r15d, %eax
cmpl 0x20(%rsp), %r15d
movq 0x28(%rsp), %rsi
jne 0x890e
addl 0x30(%rsp), %ecx
movq %r12, %rdi
movl %ecx, %esi
leaq 0x4(%rsp), %rdx
callq 0x83ba
movq %rax, %rsi
jmp 0x88e7
pushq $0x4
popq %rax
jmp 0x8af9
leaq 0x14(%rsp), %rdx
movq %r13, %rdi
movl %r14d, %esi
movq %rdx, %r13
callq 0x83ba
movq %rax, 0x20(%rsp)
leaq 0x4(%rsp), %rdx
movq %r12, %rdi
movl %ebx, %esi
callq 0x83ba
movq %rax, 0x8(%rsp)
leal -0x1(%r15), %r12d
movl (%r13), %r13d
pushq $0x1
popq %rax
leaq 0x4(%rsp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x18(%rsp)
cmpl %r15d, %r12d
jge 0x8af7
movq 0x20(%rsp), %r11
movl (%r11), %edx
addl %r13d, %edx
leal (%rax,%r14), %ecx
cmpl %ecx, %edx
jge 0x8a4c
movl %edx, 0x14(%rsp)
movq 0x8(%r11), %r11
movl %edx, %r10d
jmp 0x8a4f
movl %r13d, %r10d
movq 0x8(%rsp), %r9
movl 0x18(%rsp), %r13d
movl (%r9), %edi
addl %r13d, %edi
leal (%rax,%rbx), %edx
cmpl %edx, %edi
jge 0x8a78
movl %edi, 0x4(%rsp)
movq 0x8(%r9), %r9
movl (%r9), %esi
addl %edi, %esi
movl %edi, %r13d
jmp 0x8a7a
movl %edi, %esi
movl (%r11), %edi
addl %r10d, %edi
cmpl 0x28(%rsp), %edi
jl 0x8a8b
movl %r15d, %edi
jmp 0x8a8e
subl %r14d, %edi
leal (%rdi,%rbx), %r8d
movl %esi, %r12d
subl %ebx, %r12d
cmpl %r8d, %esi
cmovgel %edi, %r12d
movl %r13d, 0x18(%rsp)
movl %r13d, %esi
notl %esi
addl %esi, %edx
imull %ebp, %edx
movslq %edx, %rdx
movq %r9, 0x8(%rsp)
leaq (%r9,%rdx), %rdi
addq $0x18, %rdi
movl %r10d, %r13d
movl %r10d, %edx
notl %edx
addl %edx, %ecx
imull %ebp, %ecx
movslq %ecx, %rcx
movq %r11, 0x20(%rsp)
leaq (%r11,%rcx), %rsi
addq $0x18, %rsi
movl %r12d, %ecx
subl %eax, %ecx
incl %ecx
imull %ebp, %ecx
movslq %ecx, %rdx
callq 0x8220
leal 0x1(%r12), %eax
jmp 0x8a23
xorl %eax, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq