// File: CMU-SAFARI[P]MQSim/src/host/IO_Flow_Base.cpp
// Function: Host_Components::IO_Flow_Base::NVMe_read_sqe(unsigned long)
Submission_Queue_Entry* IO_Flow_Base::NVMe_read_sqe(uint64_t address)
	{
		Submission_Queue_Entry* sqe = new Submission_Queue_Entry;
		Host_IO_Request* request = request_queue_in_memory[(uint16_t)((address - nvme_queue_pair.Submission_queue_memory_base_address) / sizeof(Submission_Queue_Entry))];
		
		if (request == NULL) {
			throw std::invalid_argument(this->ID() + ": Request to access a submission queue entry that does not exist.");
		}

		sqe->Command_Identifier = request->IO_queue_info;
		if (request->Type == Host_IO_Request_Type::READ) {
			sqe->Opcode = NVME_READ_OPCODE;
			sqe->Command_specific[0] = (uint32_t) request->Start_LBA;
			sqe->Command_specific[1] = (uint32_t)(request->Start_LBA >> 32);
			sqe->Command_specific[2] = ((uint32_t)((uint16_t)request->LBA_count)) & (uint32_t)(0x0000ffff);
			sqe->PRP_entry_1 = (DATA_MEMORY_REGION);//Dummy addresses, just to emulate data read/write access
			sqe->PRP_entry_2 = (DATA_MEMORY_REGION + 0x1000);//Dummy addresses
		} else {
			sqe->Opcode = NVME_WRITE_OPCODE;
			sqe->Command_specific[0] = (uint32_t)request->Start_LBA;
			sqe->Command_specific[1] = (uint32_t)(request->Start_LBA >> 32);
			sqe->Command_specific[2] = ((uint32_t)((uint16_t)request->LBA_count)) & (uint32_t)(0x0000ffff);
			sqe->PRP_entry_1 = (DATA_MEMORY_REGION);//Dummy addresses, just to emulate data read/write access
			sqe->PRP_entry_2 = (DATA_MEMORY_REGION + 0x1000);//Dummy addresses
		}

		return sqe;
	}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x80(%rsp)
movq %rsi, 0x78(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x10(%rsp)
movl $0x48, %edi
callq 0x8450
movq 0x10(%rsp), %rcx
movq %rax, 0x70(%rsp)
movq %rcx, %rdi
addq $0xe8, %rdi
movq 0x78(%rsp), %rax
subq 0x90(%rcx), %rax
movl $0x48, %ecx
xorl %edx, %edx
divq %rcx
movzwl %ax, %eax
movl %eax, %esi
callq 0x344b0
movq (%rax), %rax
movq %rax, 0x68(%rsp)
cmpq $0x0, 0x68(%rsp)
jne 0x31f8d
movb $0x1, 0x1b(%rsp)
movl $0x10, %edi
callq 0x8200
movq 0x10(%rsp), %rsi
movq %rax, 0x8(%rsp)
leaq 0x28(%rsp), %rdi
callq 0xcdf0
jmp 0x31ee8
leaq 0x79c0d(%rip), %rdx     # 0xabafc
leaq 0x48(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0xd060
jmp 0x31f00
movq 0x8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x8750
jmp 0x31f11
movq 0x8(%rsp), %rdi
movb $0x0, 0x1b(%rsp)
movq 0xa80a6(%rip), %rsi     # 0xd9fc8
movq 0xa8087(%rip), %rdx     # 0xd9fb0
callq 0x8710
jmp 0x320a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x20(%rsp)
movl %eax, 0x1c(%rsp)
jmp 0x31f75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x20(%rsp)
movl %eax, 0x1c(%rsp)
jmp 0x31f6b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x20(%rsp)
movl %eax, 0x1c(%rsp)
leaq 0x48(%rsp), %rdi
callq 0x8848
leaq 0x28(%rsp), %rdi
callq 0x8848
testb $0x1, 0x1b(%rsp)
jne 0x31f7e
jmp 0x31f88
movq 0x8(%rsp), %rdi
callq 0x8330
jmp 0x3209b
movq 0x68(%rsp), %rax
movw 0x20(%rax), %cx
movq 0x70(%rsp), %rax
movw %cx, 0x2(%rax)
movq 0x68(%rsp), %rax
cmpl $0x0, 0x1c(%rax)
jne 0x3201d
movq 0x70(%rsp), %rax
movb $0x2, (%rax)
movq 0x68(%rsp), %rax
movq 0x10(%rax), %rax
movl %eax, %ecx
movq 0x70(%rsp), %rax
movl %ecx, 0x30(%rax)
movq 0x68(%rsp), %rax
movq 0x10(%rax), %rax
shrq $0x20, %rax
movl %eax, %ecx
movq 0x70(%rsp), %rax
movl %ecx, 0x34(%rax)
movq 0x68(%rsp), %rax
movl 0x18(%rax), %eax
movzwl %ax, %ecx
andl $0xffff, %ecx           # imm = 0xFFFF
movq 0x70(%rsp), %rax
movl %ecx, 0x38(%rax)
movq 0x70(%rsp), %rax
movabsq $0xff0000000000, %rcx   # imm = 0xFF0000000000
movq %rcx, 0x20(%rax)
movq 0x70(%rsp), %rax
movabsq $0xff0000001000, %rcx   # imm = 0xFF0000001000
movq %rcx, 0x28(%rax)
jmp 0x3208e
movq 0x70(%rsp), %rax
movb $0x1, (%rax)
movq 0x68(%rsp), %rax
movq 0x10(%rax), %rax
movl %eax, %ecx
movq 0x70(%rsp), %rax
movl %ecx, 0x30(%rax)
movq 0x68(%rsp), %rax
movq 0x10(%rax), %rax
shrq $0x20, %rax
movl %eax, %ecx
movq 0x70(%rsp), %rax
movl %ecx, 0x34(%rax)
movq 0x68(%rsp), %rax
movl 0x18(%rax), %eax
movzwl %ax, %ecx
andl $0xffff, %ecx           # imm = 0xFFFF
movq 0x70(%rsp), %rax
movl %ecx, 0x38(%rax)
movq 0x70(%rsp), %rax
movabsq $0xff0000000000, %rcx   # imm = 0xFF0000000000
movq %rcx, 0x20(%rax)
movq 0x70(%rsp), %rax
movabsq $0xff0000001000, %rcx   # imm = 0xFF0000001000
movq %rcx, 0x28(%rax)
movq 0x70(%rsp), %rax
addq $0x88, %rsp
retq
movq 0x20(%rsp), %rdi
callq 0x8770
nopw %cs:(%rax,%rax)