// File: CMU-SAFARI[P]MQSim/src/nvm_chip/flash_memory/Flash_Chip.h
// Function: NVM::FlashMemory::Flash_Chip::Get_command_execution_latency(unsigned long, unsigned int)
sim_time_type Get_command_execution_latency(command_code_type CMDCode, flash_page_ID_type pageID)
			{
				int latencyType = 0;
				if (flash_technology == Flash_Technology_Type::MLC) {
					latencyType = pageID % 2;
				} else if (flash_technology == Flash_Technology_Type::TLC) {
					//From: Yaakobi et al., "Characterization and Error-Correcting Codes for TLC Flash Memories", ICNC 2012
					latencyType = (pageID <= 5) ? 0 : ((pageID <= 7) ? 1 : (((pageID - 8) >> 1) % 3));;
				}

				switch (CMDCode)
				{
					case CMD_READ_PAGE:
					case CMD_READ_PAGE_MULTIPLANE:
					case CMD_READ_PAGE_COPYBACK:
					case CMD_READ_PAGE_COPYBACK_MULTIPLANE:
						return _readLatency[latencyType] + _RBSignalDelayRead;
					case CMD_PROGRAM_PAGE:
					case CMD_PROGRAM_PAGE_MULTIPLANE:
					case CMD_PROGRAM_PAGE_COPYBACK:
					case CMD_PROGRAM_PAGE_COPYBACK_MULTIPLANE:
						return _programLatency[latencyType] + _RBSignalDelayWrite;
					case CMD_ERASE_BLOCK:
					case CMD_ERASE_BLOCK_MULTIPLANE:
						return _eraseLatency + _RBSignalDelayErase;
					default:
						throw std::invalid_argument("Unsupported command for flash chip.");
				}
			}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x48(%rsp)
movq %rsi, 0x40(%rsp)
movl %edx, 0x3c(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x20(%rsp)
movl $0x0, 0x38(%rsp)
cmpl $0x2, 0x34(%rax)
jne 0x457d7
movl 0x3c(%rsp), %eax
andl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x4582b
movq 0x20(%rsp), %rax
cmpl $0x3, 0x34(%rax)
jne 0x45829
cmpl $0x5, 0x3c(%rsp)
ja 0x457f1
xorl %eax, %eax
movl %eax, 0x1c(%rsp)
jmp 0x45821
cmpl $0x7, 0x3c(%rsp)
ja 0x45803
movl $0x1, %edx
movl %edx, 0x18(%rsp)
jmp 0x45819
movl 0x3c(%rsp), %eax
subl $0x8, %eax
shrl %eax
movl $0x3, %ecx
xorl %edx, %edx
divl %ecx
movl %edx, 0x18(%rsp)
movl 0x18(%rsp), %eax
movl %eax, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
movl %eax, 0x38(%rsp)
jmp 0x4582b
movq 0x40(%rsp), %rax
movq %rax, 0x10(%rsp)
subq $0x30, %rax
je 0x458aa
jmp 0x4583d
movq 0x10(%rsp), %rax
subq $0x32, %rax
je 0x458aa
jmp 0x4584a
movq 0x10(%rsp), %rax
subq $0x35, %rax
je 0x458aa
jmp 0x45857
movq 0x10(%rsp), %rax
subq $0x321, %rax            # imm = 0x321
je 0x458aa
jmp 0x45866
movq 0x10(%rsp), %rax
addq $-0x60d0, %rax          # imm = 0x9F30
subq $0x2, %rax
jb 0x458ed
jmp 0x45879
movq 0x10(%rsp), %rax
addq $-0x8010, %rax          # imm = 0xFFFF7FF0
subq $0x2, %rax
jb 0x458cd
jmp 0x4588c
movq 0x10(%rsp), %rax
subq $0x8510, %rax           # imm = 0x8510
je 0x458cd
jmp 0x4589b
movq 0x10(%rsp), %rax
subq $0x85111, %rax          # imm = 0x85111
je 0x458cd
jmp 0x45904
movq 0x20(%rsp), %rcx
movq 0x58(%rcx), %rax
movslq 0x38(%rsp), %rdx
movq (%rax,%rdx,8), %rax
addq 0x80(%rcx), %rax
movq %rax, 0x50(%rsp)
jmp 0x45959
movq 0x20(%rsp), %rcx
movq 0x60(%rcx), %rax
movslq 0x38(%rsp), %rdx
movq (%rax,%rdx,8), %rax
addq 0x88(%rcx), %rax
movq %rax, 0x50(%rsp)
jmp 0x45959
movq 0x20(%rsp), %rcx
movq 0x68(%rcx), %rax
addq 0x90(%rcx), %rax
movq %rax, 0x50(%rsp)
jmp 0x45959
movl $0x10, %edi
callq 0x8200
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x8(%rsp)
leaq 0x669f3(%rip), %rsi     # 0xac313
callq 0x87d0
jmp 0x45927
movq 0x8(%rsp), %rdi
movq 0x94695(%rip), %rsi     # 0xd9fc8
movq 0x94676(%rip), %rdx     # 0xd9fb0
callq 0x8710
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x30(%rsp)
movl %eax, 0x2c(%rsp)
callq 0x8330
jmp 0x45963
movq 0x50(%rsp), %rax
addq $0x58, %rsp
retq
movq 0x30(%rsp), %rdi
callq 0x8770
nopl (%rax)