// File: /workspace/github_cpp_makefile_star2_O3/narges64[P]SIMBA/ftl.cpp
// Function: service_in_buffer(ssd_info*, sub_request*)
STATE service_in_buffer(ssd_info * ssd, sub_request * sub){
	// check mapping table and find the request
	if (sub->operation == READ){
		buffer_entry * buf_ent = NULL;
		if (ssd->dram->buffer->buffer_capacity == 0) {
			sub->buf_entry = NULL;
			service_in_flash(ssd, sub);
			return SUCCESS;
		}

		if (ssd->dram->map->map_entry[sub->lpn].buf_ent != NULL){
			buf_ent = ssd->dram->map->map_entry[sub->lpn].buf_ent;
			ssd->dram->buffer->hit_read(buf_ent);
			sub->complete_time = ssd->current_time + 1000;
			sub->buf_entry= buf_ent;
			change_subrequest_state(ssd, sub,SR_MODE_ST_S,
				ssd->current_time,SR_MODE_COMPLETE,sub->complete_time);
		}else {
			service_in_flash(ssd, sub);
		}
	}
	else if (sub->operation == WRITE){
		if (ssd->dram->buffer->buffer_capacity == 0) {
			sub->buf_entry = NULL;
			service_in_flash(ssd, sub);
			return SUCCESS;
		}
		buffer_entry * buf_ent = NULL;
		if (ssd->dram->map->map_entry[sub->lpn].buf_ent == NULL) {
			// Add a new entry to buffer
			buf_ent = ssd->dram->buffer->add_head(sub->lpn);
			sub->buf_entry = NULL;

			if (buf_ent->outlier) {
				buf_ent->sub = sub;
			}else {
				ssd->dram->map->map_entry[sub->lpn].buf_ent = buf_ent;
				// Mark the request as complete
				sub->complete_time = ssd->current_time + 1000;
				// cout << "Delay buffer add (" << sub->lpn << "," << sub->location->plane << ")  " << sub->complete_time - sub->begin_time << endl;
				change_subrequest_state(ssd, sub,SR_MODE_ST_S,ssd->current_time,
							SR_MODE_COMPLETE,sub->complete_time);
				buf_ent->sub = NULL;
			}


			sub_request * evict_sub = create_sub_request(ssd, sub->lpn,NULL, WRITE, sub->io_num);
			evict_sub->buf_entry = buf_ent;
			service_in_flash(ssd, evict_sub);

		}else {	 // write to an entry in the buffer, just need to change the entry and make it dirty
			buf_ent = ssd->dram->map->map_entry[sub->lpn].buf_ent;
			ssd->dram->buffer->hit_write(buf_ent);
			sub->complete_time = ssd->current_time + 1000;
			// cout << "Delay buffer hit (" << sub->lpn << "," << sub->location->plane << ")  " << sub->complete_time - sub->begin_time << endl;
			change_subrequest_state(ssd, sub,SR_MODE_ST_S,
					ssd->current_time,SR_MODE_COMPLETE,sub->complete_time);
			sub->buf_entry = NULL;
		}

	}
	return SUCCESS;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movl 0x20(%rsi), %eax
testl %eax, %eax
je 0x4e21
cmpl $0x1, %eax
jne 0x4e96
movq 0x60(%rbx), %rax
movq 0x18(%rax), %rdi
cmpl $0x0, 0x8(%rdi)
je 0x4e83
movq 0x10(%rax), %rax
movq (%rax), %rax
movl 0xc(%r14), %ecx
shlq $0x4, %rcx
movq 0x8(%rax,%rcx), %r15
testq %r15, %r15
je 0x4e8b
movq %r15, %rsi
callq 0x650c
movq (%rbx), %rcx
leaq 0x3e8(%rcx), %r9
movq %r9, 0x58(%r14)
movq %r15, 0x18(%r14)
movq %rbx, %rdi
movq %r14, %rsi
movl $0x1, %edx
movl $0x9, %r8d
callq 0x6d7e
jmp 0x4e96
movq 0x60(%rbx), %rax
movq 0x18(%rax), %r12
cmpl $0x0, 0x8(%r12)
je 0x4e83
movq 0x10(%rax), %rax
movq (%rax), %rax
movl 0xc(%r14), %r13d
movq %r13, %rcx
shlq $0x4, %rcx
movq 0x8(%rax,%rcx), %rsi
testq %rsi, %rsi
je 0x4eaa
movq %r12, %rdi
callq 0x6578
movq (%rbx), %rcx
leaq 0x3e8(%rcx), %r9
movq %r9, 0x58(%r14)
movq %rbx, %rdi
movq %r14, %rsi
movl $0x1, %edx
movl $0x9, %r8d
callq 0x6d7e
movq $0x0, 0x18(%r14)
jmp 0x4e96
movq $0x0, 0x18(%r14)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4f58
movl $0x1, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x28, %edi
callq 0x2190
movq %rax, %r15
xorl %ebp, %ebp
movb %bpl, 0x2(%rax)
movb %bpl, 0x8(%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movq %rbp, 0x20(%rax)
movl %r13d, 0x4(%rax)
movw $0x0, (%rax)
movq %r12, %rdi
movq %rax, %rsi
callq 0x6878
testb %al, %al
cmoveq %rbp, %r15
movq %rbp, 0x18(%r14)
movq %r14, %rax
cmpb %bpl, 0x8(%r15)
jne 0x4f31
movq 0x60(%rbx), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movl 0xc(%r14), %ecx
shlq $0x4, %rcx
movq %r15, 0x8(%rax,%rcx)
movq (%rbx), %rcx
leaq 0x3e8(%rcx), %r9
movq %r9, 0x58(%r14)
movq %rbx, %rdi
movq %r14, %rsi
movl $0x1, %edx
movl $0x9, %r8d
callq 0x6d7e
xorl %eax, %eax
movq %rax, 0x10(%r15)
movl 0x4(%r14), %r8d
movl 0xc(%r14), %esi
movq %rbx, %rdi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x4c73
movq %r15, 0x18(%rax)
movq %rbx, %rdi
movq %rax, %rsi
jmp 0x4e91