// File: narges64[P]SIMBA/ftl.cpp
// Function: write_cleanup(ssd_info*, sub_request*)
void write_cleanup(ssd_info * ssd, sub_request * sub){
	// remove the entry from the buffer since the request is done
	buffer_entry * buf_ent = sub->buf_entry;
	if (buf_ent == NULL) return;

	if (buf_ent->gc)
		ssd->dram->gc_buffer->remove_entry(buf_ent);
	else
		ssd->dram->buffer->remove_entry(buf_ent);

	int lpn = buf_ent->lpn;
	ssd->dram->map->map_entry[lpn].buf_ent = NULL;

	int64_t complete_time = sub->complete_time;

	if (buf_ent->outlier){
		if (buf_ent->sub != sub) {
			buf_ent->sub->complete_time = complete_time;

			change_subrequest_state (ssd, buf_ent->sub,
				SR_MODE_ST_S, ssd->current_time,
				SR_MODE_COMPLETE, complete_time + 1000);
		}
		buf_ent->sub->buf_entry = NULL;

		delete buf_ent;
	}else {
		if (buf_ent->sub != NULL)
			cout << "there is a problem here " << endl;

		// By removing one subrequest from buffer, we might put another sub request in the buffer
		buffer_entry * outlier_entry = NULL;
		if (buf_ent->gc)
			outlier_entry = ssd->dram->gc_buffer->move_outlier();
		else
			outlier_entry = ssd->dram->buffer->move_outlier();

		delete buf_ent;

		if (outlier_entry != NULL) {
			sub_request * outlier_sub = outlier_entry->sub;
			if (outlier_sub == NULL)
				cout << "outlier sub cannot be null" << endl;
			outlier_entry->sub = NULL;
			ssd->dram->map->map_entry[outlier_sub->lpn].buf_ent = outlier_entry;

			outlier_sub->complete_time = complete_time + 1000;

			change_subrequest_state(ssd, outlier_sub,
				SR_MODE_ST_S, ssd->current_time,
				SR_MODE_COMPLETE, complete_time+1000);
			outlier_sub->buf_entry = NULL;

		}
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x76c8
jmp 0x78fe
movq -0x18(%rbp), %rax
testb $0x1, (%rax)
je 0x76e8
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x20(%rax), %rdi
movq -0x18(%rbp), %rsi
callq 0x8d90
jmp 0x76fd
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x18(%rax), %rdi
movq -0x18(%rbp), %rsi
callq 0x8d90
movq -0x18(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movslq -0x1c(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq $0x0, 0x8(%rax)
movq -0x10(%rbp), %rax
movq 0x58(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
testb $0x1, 0x8(%rax)
je 0x77bc
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x10(%rbp), %rax
je 0x778b
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq %rcx, 0x58(%rax)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rsi
movq -0x8(%rbp), %rax
movq (%rax), %rcx
movq -0x28(%rbp), %r9
addq $0x3e8, %r9             # imm = 0x3E8
movl $0x1, %edx
movl $0x9, %r8d
callq 0x9dd0
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq $0x0, 0x18(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, %rax
je 0x77b7
movq -0x40(%rbp), %rdi
movl $0x28, %esi
callq 0x2140
jmp 0x78fe
movq -0x18(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x77e9
movq 0xc802(%rip), %rdi      # 0x13fd0
leaq 0x7e34(%rip), %rsi      # 0xf609
callq 0x2110
movq %rax, %rdi
movq 0xc7dc(%rip), %rsi      # 0x13fc0
callq 0x2150
movq $0x0, -0x30(%rbp)
movq -0x18(%rbp), %rax
testb $0x1, (%rax)
je 0x7811
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x20(%rax), %rdi
callq 0x8f00
movq %rax, -0x30(%rbp)
jmp 0x7826
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x18(%rax), %rdi
callq 0x8f00
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, %rax
je 0x7842
movq -0x48(%rbp), %rdi
movl $0x28, %esi
callq 0x2140
cmpq $0x0, -0x30(%rbp)
je 0x78fc
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
jne 0x7882
movq 0xc769(%rip), %rdi      # 0x13fd0
leaq 0x7db4(%rip), %rsi      # 0xf622
callq 0x2110
movq %rax, %rdi
movq 0xc743(%rip), %rsi      # 0x13fc0
callq 0x2150
movq -0x30(%rbp), %rax
movq $0x0, 0x10(%rax)
movq -0x30(%rbp), %rcx
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq -0x38(%rbp), %rdx
movl 0xc(%rdx), %edx
shlq $0x4, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movq -0x28(%rbp), %rcx
addq $0x3e8, %rcx            # imm = 0x3E8
movq -0x38(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x8(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq -0x8(%rbp), %rax
movq (%rax), %rcx
movq -0x28(%rbp), %r9
addq $0x3e8, %r9             # imm = 0x3E8
movl $0x1, %edx
movl $0x9, %r8d
callq 0x9dd0
movq -0x38(%rbp), %rax
movq $0x0, 0x18(%rax)
jmp 0x78fe
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)