// File: attractivechaos[P]udb2/tommyds/./tommyalloc.c
// Function: tommy_allocator_alloc
void* tommy_allocator_alloc(tommy_allocator* alloc)
{
	void* ptr;

	/* if no free block available */
	if (!alloc->free_block) {
		tommy_uintptr_t off, mis;
		tommy_size_t size;
		char* data;
		tommy_allocator_entry* segment;

		/* default allocation size */
		size = TOMMY_ALLOCATOR_BLOCK_SIZE;

		/* ensure that we can allocate at least one block */
		if (size < sizeof(tommy_allocator_entry) + alloc->align_size + alloc->block_size)
			size = sizeof(tommy_allocator_entry) + alloc->align_size + alloc->block_size;

		data = tommy_cast(char*, tommy_malloc(size));
		segment = (tommy_allocator_entry*)data;

		/* put in the segment list */
		segment->next = alloc->used_segment;
		alloc->used_segment = segment;
		data += sizeof(tommy_allocator_entry);

		/* align if not aligned */
		off = (tommy_uintptr_t)data;
		mis = off % alloc->align_size;
		if (mis != 0) {
			data += alloc->align_size - mis;
			size -= alloc->align_size - mis;
		}

		/* insert in free list */
		do {
			tommy_allocator_entry* free_block = (tommy_allocator_entry*)data;
			free_block->next = alloc->free_block;
			alloc->free_block = free_block;

			data += alloc->block_size;
			size -= alloc->block_size;
		} while (size >= alloc->block_size);
	}

	/* remove one from the free list */
	ptr = alloc->free_block;
	alloc->free_block = alloc->free_block->next;

	++alloc->count;

	return ptr;
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
movq 0x40(%rsp), %rax
cmpq $0x0, (%rax)
jne 0x27b0
movq $0xfc0, 0x20(%rsp)      # imm = 0xFC0
movq 0x20(%rsp), %rax
movq 0x40(%rsp), %rcx
movq 0x18(%rcx), %rcx
addq $0x8, %rcx
movq 0x40(%rsp), %rdx
addq 0x10(%rdx), %rcx
cmpq %rcx, %rax
jae 0x26ac
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rax
addq $0x8, %rax
movq 0x40(%rsp), %rcx
addq 0x10(%rcx), %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rdi
callq 0x1090
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x40(%rsp), %rax
movq 0x8(%rax), %rcx
movq 0x10(%rsp), %rax
movq %rcx, (%rax)
movq 0x10(%rsp), %rcx
movq 0x40(%rsp), %rax
movq %rcx, 0x8(%rax)
movq 0x18(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rax
movq 0x40(%rsp), %rcx
xorl %edx, %edx
divq 0x18(%rcx)
movq %rdx, 0x28(%rsp)
cmpq $0x0, 0x28(%rsp)
je 0x274c
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rax
subq 0x28(%rsp), %rax
addq 0x18(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rcx
subq 0x28(%rsp), %rcx
movq 0x20(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x20(%rsp)
jmp 0x274e
movq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x40(%rsp), %rax
movq (%rax), %rcx
movq 0x8(%rsp), %rax
movq %rcx, (%rax)
movq 0x8(%rsp), %rcx
movq 0x40(%rsp), %rax
movq %rcx, (%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
addq 0x18(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rcx
movq 0x20(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rax
movq 0x40(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0x274e
jmp 0x27b0
movq 0x40(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x38(%rsp)
movq 0x40(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rcx
movq 0x40(%rsp), %rax
movq %rcx, (%rax)
movq 0x40(%rsp), %rax
movl 0x20(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x20(%rax)
movq 0x38(%rsp), %rax
addq $0x48, %rsp
retq
nopl (%rax,%rax)