// File: /workspace/github_c_makefile_star2_O0/codeniko[P]CS214-Malloc-Free/mymalloc.c
// Function: myfree
void myfree(void *p, char *file, int line)
{
	struct MemEntry *ptr;
	struct MemEntry *prev;
	struct MemEntry *next;

	if (p == NULL) {
		fprintf(stderr, "Pointer is NULL in file, free failed in FILE: '%s' on LINE: '%d'\n", file, line);
		return;
	}

	ptr = (struct MemEntry*)((char*)p - sizeof(struct MemEntry));
	
	//check if valid memEntry ptr
	int i;
	int valid = 0;
	for (i = 0; i < entriesSize; i++) {
		if (ptr == memEntries[i] && !ptr->isfree) {
			valid = 1; //memEntry is valid
			break;
		}
	}
	if (!valid) {
		fprintf(stderr, "Attempting to free memory that was not malloced in FILE: '%s' on LINE: '%d'\n", file, line);
		return;
	}

	if((prev = ptr->prev) != 0 && prev->isfree)
	{
		// the previous chunk is free, so
		// merge this chunk with the previous chunk
		prev->size += sizeof(struct MemEntry) + ptr->size;
		memEntries[i] = 0; //merged with previous, so removing free memEntry
	}
	else
	{ //not setting memEntry to null b/c not necessarily removing it, just isfree=1
		ptr->isfree = 1;
		prev = ptr;	// used for the step below
	}
	if((next = ptr->next) != 0 && next->isfree)
	{
		// the next chunk is free, merge with it
		prev->size += sizeof(struct MemEntry) + next->size;
		prev->next = next->next;
		//prev->isfree = 1;
		for (i = 0; i < entriesSize; i++) {
			if (next == memEntries[i]) {
				memEntries[i] = 0; //merged with next, so removing free memEntry
				break;
			}
		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
cmpq $0x0, -0x8(%rbp)
jne 0x13ae
movq 0x2c67(%rip), %rax      # 0x3ff8
movq (%rax), %rdi
movq -0x10(%rbp), %rdx
movl -0x14(%rbp), %ecx
leaq 0xcee(%rip), %rsi       # 0x2090
movb $0x0, %al
callq 0x1030
jmp 0x151c
movq -0x8(%rbp), %rax
addq $-0x18, %rax
movq %rax, -0x20(%rbp)
movl $0x0, -0x38(%rbp)
movl $0x0, -0x34(%rbp)
cmpl $0x412, -0x34(%rbp)     # imm = 0x412
jge 0x1406
movq -0x20(%rbp), %rax
movslq -0x34(%rbp), %rdx
leaq 0x8e20(%rip), %rcx      # 0xa200
cmpq (%rcx,%rdx,8), %rax
jne 0x13f9
movq -0x20(%rbp), %rax
cmpl $0x0, 0x10(%rax)
jne 0x13f9
movl $0x1, -0x38(%rbp)
jmp 0x1406
jmp 0x13fb
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x13c8
cmpl $0x0, -0x38(%rbp)
jne 0x1430
movq 0x2be5(%rip), %rax      # 0x3ff8
movq (%rax), %rdi
movq -0x10(%rbp), %rdx
movl -0x14(%rbp), %ecx
leaq 0xcae(%rip), %rsi       # 0x20d2
movb $0x0, %al
callq 0x1030
jmp 0x151c
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
je 0x147a
movq -0x28(%rbp), %rax
cmpl $0x0, 0x10(%rax)
je 0x147a
movq -0x20(%rbp), %rax
movslq 0x14(%rax), %rdx
addq $0x18, %rdx
movq -0x28(%rbp), %rax
movslq 0x14(%rax), %rcx
addq %rdx, %rcx
movl %ecx, 0x14(%rax)
movslq -0x34(%rbp), %rcx
leaq 0x8d90(%rip), %rax      # 0xa200
movq $0x0, (%rax,%rcx,8)
jmp 0x148d
movq -0x20(%rbp), %rax
movl $0x1, 0x10(%rax)
movq -0x20(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, %rax
je 0x151c
movq -0x30(%rbp), %rax
cmpl $0x0, 0x10(%rax)
je 0x151c
movq -0x30(%rbp), %rax
movslq 0x14(%rax), %rdx
addq $0x18, %rdx
movq -0x28(%rbp), %rax
movslq 0x14(%rax), %rcx
addq %rdx, %rcx
movl %ecx, 0x14(%rax)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x8(%rax)
movl $0x0, -0x34(%rbp)
cmpl $0x412, -0x34(%rbp)     # imm = 0x412
jge 0x151a
movq -0x30(%rbp), %rax
movslq -0x34(%rbp), %rdx
leaq 0x8d0e(%rip), %rcx      # 0xa200
cmpq (%rcx,%rdx,8), %rax
jne 0x150d
movslq -0x34(%rbp), %rcx
leaq 0x8cfd(%rip), %rax      # 0xa200
movq $0x0, (%rax,%rcx,8)
jmp 0x151a
jmp 0x150f
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x14da
jmp 0x151c
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)