// File: CMU-SAFARI[P]MQSim/src/nvm_chip/flash_memory/Flash_Chip.cpp
// Function: NVM::FlashMemory::Flash_Chip::start_command_execution(NVM::FlashMemory::Flash_Command*)
void Flash_Chip::start_command_execution(Flash_Command* command)
		{
			Die* targetDie = Dies[command->Address[0].DieID];

			//If this is a simple command (not multiplane) then there should be only one address
			if (command->Address.size() > 1
				&& (command->CommandCode == CMD_READ_PAGE
					|| command->CommandCode == CMD_PROGRAM_PAGE
					|| command->CommandCode == CMD_ERASE_BLOCK)) {
				PRINT_ERROR("Flash chip " << ID() << ": executing a flash operation on a busy die!")
			}

			targetDie->Expected_finish_time = Simulator->Time() + Get_command_execution_latency(command->CommandCode, command->Address[0].PageID);
			targetDie->CommandFinishEvent = Simulator->Register_sim_event(targetDie->Expected_finish_time,
				this, command, static_cast<int>(Chip_Sim_Event_Type::COMMAND_FINISHED));
			targetDie->CurrentCMD = command;
			targetDie->Status = DieStatus::BUSY;
			idleDieNo--;

			if (status == Internal_Status::IDLE) {
				executionStartTime = Simulator->Time();
				expectedFinishTime = targetDie->Expected_finish_time;
				status = Internal_Status::BUSY;
			}

			DEBUG("Command execution started on channel: " << this->ChannelID << " chip: " << this->ChipID)
		}

// Assembly:
subq $0x98, %rsp
movq %rdi, 0x90(%rsp)
movq %rsi, 0x88(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x40(%rax), %rax
movq %rax, 0x48(%rsp)
movq 0x88(%rsp), %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x45760
movq %rax, %rcx
movq 0x48(%rsp), %rax
movl 0x8(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, 0x80(%rsp)
movq 0x88(%rsp), %rdi
addq $0x8, %rdi
callq 0x45780
cmpq $0x1, %rax
jbe 0x44578
movq 0x88(%rsp), %rax
cmpq $0x30, (%rax)
je 0x444b8
movq 0x88(%rsp), %rax
cmpq $0x8010, (%rax)         # imm = 0x8010
je 0x444b8
movq 0x88(%rsp), %rax
cmpq $0x60d0, (%rax)         # imm = 0x60D0
jne 0x44578
movq 0x95b31(%rip), %rdi     # 0xd9ff0
movq %rdi, 0x20(%rsp)
leaq 0x6641d(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x20(%rsp), %rdi
leaq 0x67c94(%rip), %rsi     # 0xac170
callq 0x8440
movq 0x40(%rsp), %rsi
movq %rax, 0x28(%rsp)
leaq 0x60(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0xcdf0
movq 0x28(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x83e0
movq %rax, 0x38(%rsp)
jmp 0x44510
movq 0x38(%rsp), %rdi
leaq 0x67c93(%rip), %rsi     # 0xac1af
callq 0x8440
movq %rax, 0x18(%rsp)
jmp 0x44528
movq 0x18(%rsp), %rdi
movq 0x95a24(%rip), %rsi     # 0xd9f58
callq 0x8480
jmp 0x4453b
leaq 0x60(%rsp), %rdi
callq 0x8848
movq 0x95a84(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x58(%rsp)
movl %eax, 0x54(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x8848
jmp 0x44682
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, 0x10(%rsp)
movq 0x88(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x8(%rsp)
movq 0x88(%rsp), %rdi
addq $0x8, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x45760
movq 0x8(%rsp), %rsi
movq 0x40(%rsp), %rdi
movl 0x14(%rax), %edx
callq 0x457a0
movq 0x10(%rsp), %rcx
addq %rax, %rcx
movq 0x80(%rsp), %rax
movq %rcx, 0x18(%rax)
callq 0x46500
movq 0x40(%rsp), %rdx
movq %rax, %rdi
movq 0x80(%rsp), %rax
movq 0x18(%rax), %rsi
movq 0x88(%rsp), %rcx
xorl %r8d, %r8d
callq 0x46c60
movq %rax, %rdx
movq 0x40(%rsp), %rax
movq 0x80(%rsp), %rcx
movq %rdx, 0x10(%rcx)
movq 0x88(%rsp), %rdx
movq 0x80(%rsp), %rcx
movq %rdx, 0x28(%rcx)
movq 0x80(%rsp), %rcx
movl $0x0, 0xc(%rcx)
movl 0x3c(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x3c(%rax)
cmpl $0x0, 0x38(%rax)
jne 0x4467a
callq 0x46500
movq %rax, %rdi
callq 0x46c50
movq %rax, %rcx
movq 0x40(%rsp), %rax
movq %rcx, 0xa0(%rax)
movq 0x80(%rsp), %rcx
movq 0x18(%rcx), %rcx
movq %rcx, 0xa8(%rax)
movl $0x1, 0x38(%rax)
addq $0x98, %rsp
retq
movq 0x58(%rsp), %rdi
callq 0x8770
nopl (%rax)