// File: 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
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x1, 0x20(%rax)
jne 0x633c
movq $0x0, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x18(%rax), %rax
cmpl $0x0, 0x8(%rax)
jne 0x627d
movq -0x18(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x6540
movl $0x1, -0x4(%rbp)
jmp 0x652d
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
movl 0xc(%rcx), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
cmpq $0x0, 0x8(%rax)
je 0x632a
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
movl 0xc(%rcx), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x18(%rax), %rdi
movq -0x20(%rbp), %rsi
callq 0x8b60
movq -0x10(%rbp), %rax
movq (%rax), %rcx
addq $0x3e8, %rcx            # imm = 0x3E8
movq -0x18(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x18(%rbp), %rax
movq 0x58(%rax), %r9
movl $0x1, %edx
movl $0x9, %r8d
callq 0x9dd0
jmp 0x6337
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x6540
jmp 0x6526
movq -0x18(%rbp), %rax
cmpl $0x0, 0x20(%rax)
jne 0x6524
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x18(%rax), %rax
cmpl $0x0, 0x8(%rax)
jne 0x6381
movq -0x18(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x6540
movl $0x1, -0x4(%rbp)
jmp 0x652d
movq $0x0, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
movl 0xc(%rcx), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
cmpq $0x0, 0x8(%rax)
jne 0x649f
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x18(%rax), %rdi
movq -0x18(%rbp), %rax
movl 0xc(%rax), %esi
callq 0x8be0
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x28(%rbp), %rax
testb $0x1, 0x8(%rax)
je 0x63f1
movq -0x18(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x10(%rax)
jmp 0x645f
movq -0x28(%rbp), %rcx
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rdx
movl 0xc(%rdx), %edx
shlq $0x4, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rcx
addq $0x3e8, %rcx            # imm = 0x3E8
movq -0x18(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x18(%rbp), %rax
movq 0x58(%rax), %r9
movl $0x1, %edx
movl $0x9, %r8d
callq 0x9dd0
movq -0x28(%rbp), %rax
movq $0x0, 0x10(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0xc(%rax), %esi
movq -0x18(%rbp), %rax
movl 0x4(%rax), %r8d
xorl %eax, %eax
movl %eax, %edx
xorl %ecx, %ecx
callq 0x5ff0
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x6540
jmp 0x6522
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x10(%rax), %rax
movq (%rax), %rax
movq -0x18(%rbp), %rcx
movl 0xc(%rcx), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x60(%rax), %rax
movq 0x18(%rax), %rdi
movq -0x28(%rbp), %rsi
callq 0x8c70
movq -0x10(%rbp), %rax
movq (%rax), %rcx
addq $0x3e8, %rcx            # imm = 0x3E8
movq -0x18(%rbp), %rax
movq %rcx, 0x58(%rax)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x10(%rbp), %rax
movq (%rax), %rcx
movq -0x18(%rbp), %rax
movq 0x58(%rax), %r9
movl $0x1, %edx
movl $0x9, %r8d
callq 0x9dd0
movq -0x18(%rbp), %rax
movq $0x0, 0x18(%rax)
jmp 0x6524
jmp 0x6526
movl $0x1, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)