// File: attractivechaos[P]udb2/tommyds/./tommychain.h
// Function: tommy_chain_mergesort
tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp)
{
	/*
	 * Bit buckets of chains.
	 * Each bucket contains 2^i nodes or it's empty.
	 * The chain at address TOMMY_CHAIN_BIT_MAX is an independet variable operating as "carry".
	 * We keep it in the same "bit" vector to avoid reports from the valgrind tool sgcheck.
	 */
	tommy_chain bit[TOMMY_CHAIN_BIT_MAX + 1];

	/**
	 * Value stored inside the bit bucket.
	 * It's used to know which bucket is empty of full.
	 */
	tommy_count_t counter;
	tommy_node* node = chain->head;
	tommy_node* tail = chain->tail;
	tommy_count_t mask;
	tommy_count_t i;

	counter = 0;
	while (1) {
		tommy_node* next;
		tommy_chain* last;

		/* carry bit to add */
		last = &bit[TOMMY_CHAIN_BIT_MAX];
		bit[TOMMY_CHAIN_BIT_MAX].head = node;
		bit[TOMMY_CHAIN_BIT_MAX].tail = node;
		next = node->next;

		/* add the bit, propagating the carry */
		i = 0;
		mask = counter;
		while ((mask & 1) != 0) {
			tommy_chain_merge_degenerated(&bit[i], last, cmp);
			mask >>= 1;
			last = &bit[i];
			++i;
		}

		/* copy the carry in the first empty bit */
		bit[i] = *last;

		/* add the carry in the counter */
		++counter;

		if (node == tail)
			break;
		node = next;
	}

	/* merge the buckets */
	i = tommy_ctz_u32(counter);
	mask = counter >> i;
	while (mask != 1) {
		mask >>= 1;
		if (mask & 1)
			tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp);
		else
			bit[i + 1] = bit[i];
		++i;
	}

	*chain = bit[i];
}

// Assembly:
subq $0x258, %rsp            # imm = 0x258
movq %rdi, 0x250(%rsp)
movq %rsi, 0x248(%rsp)
movq 0x250(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x20(%rsp)
movq 0x250(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x18(%rsp)
movl $0x0, 0x2c(%rsp)
leaq 0x30(%rsp), %rax
addq $0x200, %rax            # imm = 0x200
movq %rax, (%rsp)
movq 0x20(%rsp), %rax
movq %rax, 0x230(%rsp)
movq 0x20(%rsp), %rax
movq %rax, 0x238(%rsp)
movq 0x20(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x8(%rsp)
movl $0x0, 0x10(%rsp)
movl 0x2c(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x14(%rsp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x31c0
movl 0x10(%rsp), %eax
leaq 0x30(%rsp), %rdi
shlq $0x4, %rax
addq %rax, %rdi
movq (%rsp), %rsi
movq 0x248(%rsp), %rdx
callq 0x5b70
movl 0x14(%rsp), %eax
shrl %eax
movl %eax, 0x14(%rsp)
movl 0x10(%rsp), %eax
movl %eax, %ecx
leaq 0x30(%rsp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, (%rsp)
movl 0x10(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10(%rsp)
jmp 0x3166
movl 0x10(%rsp), %eax
movl %eax, %ecx
leaq 0x30(%rsp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rsp), %rcx
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
movq 0x20(%rsp), %rax
cmpq 0x18(%rsp), %rax
jne 0x31fd
jmp 0x320c
movq 0x8(%rsp), %rax
movq %rax, 0x20(%rsp)
jmp 0x3120
movl 0x2c(%rsp), %edi
callq 0x5c40
movl %eax, 0x10(%rsp)
movl 0x2c(%rsp), %eax
movl 0x10(%rsp), %ecx
shrl %cl, %eax
movl %eax, 0x14(%rsp)
cmpl $0x1, 0x14(%rsp)
je 0x32c3
movl 0x14(%rsp), %eax
shrl %eax
movl %eax, 0x14(%rsp)
movl 0x14(%rsp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x327c
movl 0x10(%rsp), %eax
addl $0x1, %eax
movl %eax, %eax
leaq 0x30(%rsp), %rdi
shlq $0x4, %rax
addq %rax, %rdi
movl 0x10(%rsp), %eax
leaq 0x30(%rsp), %rsi
shlq $0x4, %rax
addq %rax, %rsi
movq 0x248(%rsp), %rdx
callq 0x5b70
jmp 0x32b3
movl 0x10(%rsp), %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %ecx
leaq 0x30(%rsp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x10(%rsp), %ecx
movl %ecx, %edx
leaq 0x30(%rsp), %rcx
shlq $0x4, %rdx
addq %rdx, %rcx
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
movl 0x10(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10(%rsp)
jmp 0x3227
movq 0x250(%rsp), %rax
movl 0x10(%rsp), %ecx
movl %ecx, %edx
leaq 0x30(%rsp), %rcx
shlq $0x4, %rdx
addq %rdx, %rcx
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
addq $0x258, %rsp            # imm = 0x258
retq
nopw %cs:(%rax,%rax)