// File: /workspace/github_c_makefile_star2_O2/nh13[P]ksw/src/ksw2/kalloc.c
// Function: kmalloc
void *kmalloc(void *_km, size_t n_bytes)
{
	kmem_t *km = (kmem_t*)_km;
	size_t n_units, *p, *q;

	if (n_bytes == 0) return 0;
	if (km == 0) return malloc(n_bytes);
	/* "n_units" means the number of units. The size of one unit equals to sizeof(kheader_t).
	 * "1" is the kheader_t of a block, which is always required. */
	n_units = 1 + (n_bytes + sizeof(size_t) - 1) / sizeof(size_t);
	if (n_units&1) ++n_units; /* make n_units an even number, or it will segfault if only one unit remains */

	if (!(q = km->loop_head)) { /* the first time when kmalloc() is called, intialization */
		km->base[1] = (size_t)(km->loop_head = q = km->base); *q = 0;
	}
	for (p = PTR(q);; q = p, p = PTR(p)) { /* search for a suitable block */
		if (*p >= n_units) { /* p->size if the size of current block. This line means the current block is large enough. */
			if (*p == n_units) q[1] = (size_t)PTR(p); /* no need to split the block */
			else { /* split the block */
				/* memory is allocated at the end of the block */
				*p -= n_units; /* reduce the size of the free block */
				p += *p; /* skip to the kheader_t of the allocated block */
				*p = n_units; /* set the size */
			}
			km->loop_head = q; /* set the end of chain */
			return p + 1; /* skip the kheader_t */
		}
		if (p == km->loop_head) { /* then ask for more "cores" */
			if ((p = morecore(km, n_units)) == 0) return 0;
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
testq %rsi, %rsi
je 0x19e605
movq %rdi, %rbx
testq %rdi, %rdi
je 0x19e609
addq $0x7, %rsi
movq %rsi, %r12
shrq $0x3, %r12
andl $0x8, %esi
cmpq $0x1, %rsi
adcq $0x1, %r12
movq 0x10(%rbx), %rax
testq %rax, %rax
jne 0x19e560
movq %rbx, 0x10(%rbx)
movq %rbx, 0x8(%rbx)
andq $0x0, (%rbx)
movq %rbx, %rax
leaq 0xfffff(%r12), %rcx
movabsq $0x7ffffffffff00000, %r14 # imm = 0x7FFFFFFFFFF00000
andq %rcx, %r14
leaq (,%r14,8), %r13
leaq 0x18(%rbx), %rcx
movq %rcx, (%rsp)
movq %rax, %rcx
movq 0x8(%rcx), %rdx
movq (%rdx), %rsi
subq %r12, %rsi
jae 0x19e5f9
movq %rdx, %rcx
cmpq %rdx, %rax
jne 0x19e588
movq %r13, %rdi
callq 0x19e150
testq %rax, %rax
je 0x19e643
movq %rax, %rbp
movq 0x28(%rbx), %r15
testq %r15, %r15
cmoveq (%rsp), %r15
movq %rax, 0x8(%r15)
pushq $0x1
popq %rdi
pushq $0x10
popq %rsi
callq 0x19e0b0
movq %rax, (%r15)
movq %rax, 0x28(%rbx)
addq %r13, 0x30(%rbx)
movq %r14, (%rbp)
addq $0x8, %rbp
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x19e38c
movq 0x10(%rbx), %rax
testq %rax, %rax
movl $0x0, %edx
jne 0x19e585
jmp 0x19e631
jne 0x19e61f
movq 0x8(%rdx), %rax
movq %rax, 0x8(%rcx)
jmp 0x19e629
xorl %edx, %edx
jmp 0x19e631
movq %rsi, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x19e150
movq %rsi, (%rdx)
leaq (%rdx,%rsi,8), %rdx
movq %r12, (%rdx)
movq %rcx, 0x10(%rbx)
addq $0x8, %rdx
movq %rdx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x19e6b1
movq 0x59c986(%rip), %rax    # 0x73afd8
movq (%rax), %rdi
leaq 0x3c9ab9(%rip), %rsi    # 0x568115
movq %r13, %rdx
xorl %eax, %eax
callq 0x19e180
pushq $0x1
popq %rdi
callq 0x19e130