// File: /workspace/github_c_makefile_star2_O1/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 %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq 0x8(%rdi), %rbp
movl $0x3, %eax
testq %rbp, %rbp
je 0x8b54
movq %rdx, %r12
movq 0x8(%rdx), %r14
testq %r14, %r14
je 0x8b54
movq %rdi, %r13
movl 0x10(%rdi), %r9d
movl $0x4, %eax
cmpl 0x10(%r12), %r9d
jne 0x8b54
testl %r8d, %r8d
je 0x8b52
movl $0x2, %eax
testl %esi, %esi
jle 0x8b54
cmpl %esi, (%r13)
jl 0x8b54
testl %ecx, %ecx
jle 0x8b54
cmpl %ecx, (%r12)
jl 0x8b54
leal (%r8,%rsi), %edx
movl %edx, 0x8(%rsp)
cmpl $0x2, %edx
jl 0x8b54
leal (%r8,%rsi), %edx
decl %edx
cmpl %edx, (%r13)
jl 0x8b54
leal (%r8,%rcx), %edi
cmpl $0x2, %edi
jl 0x8b54
leal (%r8,%rcx), %edi
decl %edi
cmpl %edi, (%r12)
jl 0x8b54
cmpq %r12, %r13
movq %rcx, 0x10(%rsp)
movq %rsi, 0x20(%rsp)
movl %r9d, 0xc(%rsp)
jne 0x8927
cmpl %ecx, %esi
jg 0x8927
cmpl %ecx, 0x8(%rsp)
jle 0x8927
cmpl %ecx, %esi
jge 0x8b52
movl (%rbp), %eax
movl $0x1, %ebx
cmpl %edx, %eax
jge 0x8a25
movl %eax, %r15d
movq 0x8(%rbp), %rbp
movl (%rbp), %eax
addl %r15d, %eax
cmpl %edx, %eax
jl 0x890e
incl %r15d
jmp 0x8a2b
movl (%rbp), %eax
movl $0x1, %ebx
cmpl %esi, %eax
jge 0x8949
movl %eax, %r15d
movq 0x8(%rbp), %rbp
movl (%rbp), %eax
addl %r15d, %eax
cmpl %esi, %eax
jl 0x8933
incl %r15d
jmp 0x894f
movl $0x1, %r15d
movl (%r14), %eax
cmpl %ecx, %eax
jge 0x8967
movl %eax, %ebx
movq 0x8(%r14), %r14
movl (%r14), %eax
addl %ebx, %eax
cmpl %ecx, %eax
jl 0x8956
incl %ebx
movl $0x1, %eax
movl (%rbp), %edx
addl %r15d, %edx
leal (%rax,%rsi), %ecx
cmpl %ecx, %edx
jge 0x8980
movq 0x8(%rbp), %rbp
movl %edx, %r15d
movq 0x10(%rsp), %r9
movl 0xc(%rsp), %r11d
movl (%r14), %edi
addl %ebx, %edi
leal (%rax,%r9), %edx
cmpl %edx, %edi
jge 0x899d
movq 0x8(%r14), %r14
movl %edi, %ebx
movl (%rbp), %r10d
addl %r15d, %r10d
cmpl 0x8(%rsp), %r10d
jl 0x89b0
movl %r8d, %r10d
jmp 0x89b3
subl %esi, %r10d
movq %r8, %r13
movl (%r14), %edi
addl %ebx, %edi
leal (%r10,%r9), %r8d
movl %edi, %r12d
subl %r9d, %r12d
cmpl %r8d, %edi
cmovgel %r10d, %r12d
movl %ebx, %esi
notl %esi
addl %esi, %edx
imull %r11d, %edx
movslq %edx, %rdx
leaq (%r14,%rdx), %rdi
addq $0x18, %rdi
movl %r15d, %edx
notl %edx
addl %edx, %ecx
imull %r11d, %ecx
movslq %ecx, %rcx
leaq (%rcx,%rbp), %rsi
addq $0x18, %rsi
movl %r12d, %ecx
subl %eax, %ecx
incl %ecx
imull %r11d, %ecx
movslq %ecx, %rdx
callq 0x8220
leal 0x1(%r12), %eax
cmpl %r13d, %r12d
movq 0x20(%rsp), %rsi
movq %r13, %r8
jl 0x896c
jmp 0x8b52
movl $0x1, %r15d
movl (%r14), %eax
cmpl %edi, %eax
jge 0x8a43
movl %eax, %ebx
movq 0x8(%r14), %r14
movl (%r14), %eax
addl %ebx, %eax
cmpl %edi, %eax
jl 0x8a32
incl %ebx
testl %r8d, %r8d
jle 0x8b52
leal -0x1(%rsi), %eax
movq %rax, 0x28(%rsp)
leal -0x1(%rcx), %eax
movl %eax, 0x18(%rsp)
incl %r8d
movl %r8d, %eax
movl %r15d, %edx
subl %esi, %edx
leal 0x1(%rdx), %edx
movl %edx, 0x1c(%rsp)
movl $0x1, %r8d
cmovgl %edx, %r8d
leal (%r8,%rcx), %edx
movl %ebx, %edi
subl %ecx, %edi
incl %edi
cmpl %edx, %ebx
movl %edi, 0x8(%rsp)
cmovgel %edi, %r8d
movl %ebx, %edx
notl %edx
addl %ecx, %edx
addl %r8d, %edx
imull %r9d, %edx
movslq %edx, %rcx
leaq (%r14,%rcx), %rdi
addq $0x18, %rdi
movl %r15d, %ecx
notl %ecx
addl %esi, %ecx
movq %r8, 0x30(%rsp)
addl %r8d, %ecx
imull %r9d, %ecx
movslq %ecx, %rcx
leaq (%rcx,%rbp), %rsi
addq $0x18, %rsi
subl %r8d, %eax
imull %r9d, %eax
movslq %eax, %rdx
callq 0x8220
movq 0x30(%rsp), %r8
leal -0x1(%r8), %eax
cmpl 0x1c(%rsp), %r8d
jne 0x8b0c
movq 0x28(%rsp), %rcx
addl %eax, %ecx
movq 0x8(%r13), %rbp
movl (%rbp), %edx
movl $0x1, %r15d
cmpl %ecx, %edx
jge 0x8b0c
movl %edx, %r15d
movq 0x8(%rbp), %rbp
movl (%rbp), %edx
addl %r15d, %edx
cmpl %ecx, %edx
jl 0x8af8
incl %r15d
cmpl 0x8(%rsp), %r8d
movq 0x10(%rsp), %rcx
movq 0x20(%rsp), %rsi
movl 0xc(%rsp), %r9d
jne 0x8b48
addl 0x18(%rsp), %eax
movq 0x8(%r12), %r14
movl (%r14), %edx
movl $0x1, %ebx
cmpl %eax, %edx
jge 0x8b48
movl %edx, %ebx
movq 0x8(%r14), %r14
movl (%r14), %edx
addl %ebx, %edx
cmpl %eax, %edx
jl 0x8b37
incl %ebx
cmpl $0x1, %r8d
jg 0x8a5e
xorl %eax, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq