// File: /workspace/github_cpp_makefile_star2_O1/CMU-SAFARI[P]MQSim/src/ssd/NVM_PHY_ONFI_NVDDR2.cpp
// Function: SSD_Components::NVM_PHY_ONFI_NVDDR2::Send_command_to_chip(std::__cxx11::list<SSD_Components::NVM_Transaction_Flash*, std::allocator<SSD_Components::NVM_Transaction_Flash*>>&)
void NVM_PHY_ONFI_NVDDR2::Send_command_to_chip(std::list<NVM_Transaction_Flash*>& transaction_list)
	{
		ONFI_Channel_NVDDR2* target_channel = channels[transaction_list.front()->Address.ChannelID];

		NVM::FlashMemory::Flash_Chip* targetChip = target_channel->Chips[transaction_list.front()->Address.ChipID];
		ChipBookKeepingEntry* chipBKE = &bookKeepingTable[transaction_list.front()->Address.ChannelID][transaction_list.front()->Address.ChipID];
		DieBookKeepingEntry* dieBKE = &chipBKE->Die_book_keeping_records[transaction_list.front()->Address.DieID];

		/*If this is not a die-interleaved command execution, and the channel is already busy,
		* then something illegarl is happening*/
		if (target_channel->GetStatus() == BusChannelStatus::BUSY && chipBKE->OngoingDieCMDTransfers.size() == 0) {
			PRINT_ERROR("Bus " << target_channel->ChannelID << ": starting communication on a busy flash channel!");
		}

		sim_time_type suspendTime = 0;
		if (!dieBKE->Free) {
			if (transaction_list.front()->SuspendRequired) {
				switch (dieBKE->ActiveTransactions.front()->Type) {
					case Transaction_Type::WRITE:
						Stats::IssuedSuspendProgramCMD++;
						suspendTime = target_channel->ProgramSuspendCommandTime + targetChip->GetSuspendProgramTime();
						break;
					case Transaction_Type::ERASE:
						Stats::IssuedSuspendEraseCMD++;
						suspendTime = target_channel->EraseSuspendCommandTime + targetChip->GetSuspendEraseTime();
						break;
					default:
						PRINT_ERROR("Read suspension is not supported!")
				}
				targetChip->Suspend(transaction_list.front()->Address.DieID);
				dieBKE->PrepareSuspend();
				if (chipBKE->OngoingDieCMDTransfers.size()) {
					chipBKE->PrepareSuspend();
				}
			} else {
				PRINT_ERROR("Read suspension is not supported!")
			}
		}

		dieBKE->Free = false;
		dieBKE->ActiveCommand = new NVM::FlashMemory::Flash_Command();
		for (std::list<NVM_Transaction_Flash*>::iterator it = transaction_list.begin();
			it != transaction_list.end(); it++) {
			dieBKE->ActiveTransactions.push_back(*it);
			dieBKE->ActiveCommand->Address.push_back((*it)->Address);
			NVM::FlashMemory::PageMetadata metadata;
			metadata.LPA = (*it)->LPA;
			dieBKE->ActiveCommand->Meta_data.push_back(metadata);
		}

		switch (transaction_list.front()->Type) {
			case Transaction_Type::READ:
				if (transaction_list.size() == 1) {
					Stats::IssuedReadCMD++;
					dieBKE->ActiveCommand->CommandCode = CMD_READ_PAGE;
					DEBUG("Chip " << targetChip->ChannelID << ", " << targetChip->ChipID << ", " << transaction_list.front()->Address.DieID << ": Sending read command to chip for LPA: " << transaction_list.front()->LPA)
				} else {
					Stats::IssuedMultiplaneReadCMD++;
					dieBKE->ActiveCommand->CommandCode = CMD_READ_PAGE_MULTIPLANE;
					DEBUG("Chip " << targetChip->ChannelID << ", " << targetChip->ChipID << ", " << transaction_list.front()->Address.DieID << ": Sending multi-plane read command to chip for LPA: " << transaction_list.front()->LPA)
				}

				for (std::list<NVM_Transaction_Flash*>::iterator it = transaction_list.begin();
					it != transaction_list.end(); it++) {
					(*it)->STAT_transfer_time += target_channel->ReadCommandTime[transaction_list.size()];
				}
				if (chipBKE->OngoingDieCMDTransfers.size() == 0) {
					targetChip->StartCMDXfer();
					chipBKE->Status = ChipStatus::CMD_IN;
					chipBKE->Last_transfer_finish_time = Simulator->Time() + suspendTime + target_channel->ReadCommandTime[transaction_list.size()];
					Simulator->Register_sim_event(Simulator->Time() + suspendTime + target_channel->ReadCommandTime[transaction_list.size()], this,
						dieBKE, (int)NVDDR2_SimEventType::READ_CMD_ADDR_TRANSFERRED);
				} else {
					dieBKE->DieInterleavedTime = suspendTime + target_channel->ReadCommandTime[transaction_list.size()];
					chipBKE->Last_transfer_finish_time += suspendTime + target_channel->ReadCommandTime[transaction_list.size()];
				}
				chipBKE->OngoingDieCMDTransfers.push(dieBKE);

				dieBKE->Expected_finish_time = chipBKE->Last_transfer_finish_time + targetChip->Get_command_execution_latency(dieBKE->ActiveCommand->CommandCode, dieBKE->ActiveCommand->Address[0].PageID);
				if (chipBKE->Expected_command_exec_finish_time < dieBKE->Expected_finish_time) {
					chipBKE->Expected_command_exec_finish_time = dieBKE->Expected_finish_time;
				}
				break;
			case Transaction_Type::WRITE:
				if (((NVM_Transaction_Flash_WR*)transaction_list.front())->ExecutionMode == WriteExecutionModeType::SIMPLE) {
					if (transaction_list.size() == 1) {
						Stats::IssuedProgramCMD++;
						dieBKE->ActiveCommand->CommandCode = CMD_PROGRAM_PAGE;
						DEBUG("Chip " << targetChip->ChannelID << ", " << targetChip->ChipID << ", " << transaction_list.front()->Address.DieID << ": Sending program command to chip for LPA: " << transaction_list.front()->LPA)
					} else {
						Stats::IssuedMultiplaneProgramCMD++;
						dieBKE->ActiveCommand->CommandCode = CMD_PROGRAM_PAGE_MULTIPLANE;
						DEBUG("Chip " << targetChip->ChannelID << ", " << targetChip->ChipID << ", " << transaction_list.front()->Address.DieID << ": Sending multi-plane program command to chip for LPA: " << transaction_list.front()->LPA)
					}

					sim_time_type data_transfer_time = 0;

					for (std::list<NVM_Transaction_Flash*>::iterator it = transaction_list.begin();
						it != transaction_list.end(); it++) {
						(*it)->STAT_transfer_time += target_channel->ProgramCommandTime[transaction_list.size()] + NVDDR2DataInTransferTime((*it)->Data_and_metadata_size_in_byte, target_channel);
						data_transfer_time += NVDDR2DataInTransferTime((*it)->Data_and_metadata_size_in_byte, target_channel);
					}
					if (chipBKE->OngoingDieCMDTransfers.size() == 0) {
						targetChip->StartCMDDataInXfer();
						chipBKE->Status = ChipStatus::CMD_DATA_IN;
						chipBKE->Last_transfer_finish_time = Simulator->Time() + suspendTime + target_channel->ProgramCommandTime[transaction_list.size()] + data_transfer_time;
						Simulator->Register_sim_event(Simulator->Time() + suspendTime + target_channel->ProgramCommandTime[transaction_list.size()] + data_transfer_time,
							this, dieBKE, (int)NVDDR2_SimEventType::PROGRAM_CMD_ADDR_DATA_TRANSFERRED);
					} else {
						dieBKE->DieInterleavedTime = suspendTime + target_channel->ProgramCommandTime[transaction_list.size()] + data_transfer_time;
						chipBKE->Last_transfer_finish_time += suspendTime + target_channel->ProgramCommandTime[transaction_list.size()] + data_transfer_time;
					}
					chipBKE->OngoingDieCMDTransfers.push(dieBKE);

					dieBKE->Expected_finish_time = chipBKE->Last_transfer_finish_time + targetChip->Get_command_execution_latency(dieBKE->ActiveCommand->CommandCode, dieBKE->ActiveCommand->Address[0].PageID);
					if (chipBKE->Expected_command_exec_finish_time < dieBKE->Expected_finish_time) {
						chipBKE->Expected_command_exec_finish_time = dieBKE->Expected_finish_time;
					}
				} else {
					//Copyback write for GC

					if (transaction_list.size() == 1) {
						Stats::IssuedCopybackReadCMD++;
						dieBKE->ActiveCommand->CommandCode = CMD_READ_PAGE_COPYBACK;
					} else {
						Stats::IssuedMultiplaneCopybackProgramCMD++;
						dieBKE->ActiveCommand->CommandCode = CMD_READ_PAGE_COPYBACK_MULTIPLANE;
					}

					for (std::list<NVM_Transaction_Flash*>::iterator it = transaction_list.begin();
						it != transaction_list.end(); it++) {
						(*it)->STAT_transfer_time += target_channel->ReadCommandTime[transaction_list.size()];
					}
					if (chipBKE->OngoingDieCMDTransfers.size() == 0) {
						targetChip->StartCMDXfer();
						chipBKE->Status = ChipStatus::CMD_IN;
						chipBKE->Last_transfer_finish_time = Simulator->Time() + suspendTime + target_channel->ReadCommandTime[transaction_list.size()];
						Simulator->Register_sim_event(Simulator->Time() + suspendTime + target_channel->ReadCommandTime[transaction_list.size()], this,
							dieBKE, (int)NVDDR2_SimEventType::READ_CMD_ADDR_TRANSFERRED);
					} else {
						dieBKE->DieInterleavedTime = suspendTime + target_channel->ReadCommandTime[transaction_list.size()];
						chipBKE->Last_transfer_finish_time += suspendTime + target_channel->ReadCommandTime[transaction_list.size()];
					}
					chipBKE->OngoingDieCMDTransfers.push(dieBKE);

					dieBKE->Expected_finish_time = chipBKE->Last_transfer_finish_time + targetChip->Get_command_execution_latency(dieBKE->ActiveCommand->CommandCode, dieBKE->ActiveCommand->Address[0].PageID);
					if (chipBKE->Expected_command_exec_finish_time < dieBKE->Expected_finish_time) {
						chipBKE->Expected_command_exec_finish_time = dieBKE->Expected_finish_time;
					}
				}
				break;
			case Transaction_Type::ERASE:
				//DEBUG2("Chip " << targetChip->ChannelID << ", " << targetChip->ChipID << ", " << transaction_list.front()->Address.DieID << ": Sending erase command to chip")
				if (transaction_list.size() == 1) {
					Stats::IssuedEraseCMD++;
					dieBKE->ActiveCommand->CommandCode = CMD_ERASE_BLOCK;
				} else {
					Stats::IssuedMultiplaneEraseCMD++;
					dieBKE->ActiveCommand->CommandCode = CMD_ERASE_BLOCK_MULTIPLANE;
				}

				for (std::list<NVM_Transaction_Flash*>::iterator it = transaction_list.begin();
					it != transaction_list.end(); it++) {
					(*it)->STAT_transfer_time += target_channel->EraseCommandTime[transaction_list.size()];
				}
				if (chipBKE->OngoingDieCMDTransfers.size() == 0) {
					targetChip->StartCMDXfer();
					chipBKE->Status = ChipStatus::CMD_IN;
					chipBKE->Last_transfer_finish_time = Simulator->Time() + suspendTime + target_channel->EraseCommandTime[transaction_list.size()];
					Simulator->Register_sim_event(Simulator->Time() + suspendTime + target_channel->EraseCommandTime[transaction_list.size()],
						this, dieBKE, (int)NVDDR2_SimEventType::ERASE_SETUP_COMPLETED);
				} else {
					dieBKE->DieInterleavedTime = suspendTime + target_channel->EraseCommandTime[transaction_list.size()];
					chipBKE->Last_transfer_finish_time += suspendTime + target_channel->EraseCommandTime[transaction_list.size()];
				}
				chipBKE->OngoingDieCMDTransfers.push(dieBKE);

				dieBKE->Expected_finish_time = chipBKE->Last_transfer_finish_time + targetChip->Get_command_execution_latency(dieBKE->ActiveCommand->CommandCode, dieBKE->ActiveCommand->Address[0].PageID);
				if (chipBKE->Expected_command_exec_finish_time < dieBKE->Expected_finish_time) {
					chipBKE->Expected_command_exec_finish_time = dieBKE->Expected_finish_time;
				}
				break;
			default:
				throw std::invalid_argument("NVM_PHY_ONFI_NVDDR2: Unhandled event specified!");
		}

		target_channel->SetStatus(BusChannelStatus::BUSY, targetChip);
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %r12
movq (%rsi), %rax
movq 0x10(%rax), %rax
movl 0x38(%rax), %ecx
movl 0x3c(%rax), %edx
movq 0x88(%rdi), %rsi
movq 0x90(%rdi), %r8
movq (%rsi,%rcx,8), %rbx
movq 0x8(%rbx), %rsi
movq (%rsi,%rdx,8), %r15
movq (%r8,%rcx,8), %rsi
shlq $0x7, %rdx
movl 0x40(%rax), %ecx
imulq $0x68, %rcx, %rcx
addq 0x8(%rsi,%rdx), %rcx
leaq (%rsi,%rdx), %r13
movq %rcx, 0x8(%rsp)
cmpl $0x0, 0x14(%rbx)
jne 0x46450
movq 0x70(%r13), %rdx
movq %rdx, %rsi
subq 0x50(%r13), %rsi
shrq $0x3, %rsi
cmpq $0x1, %rdx
adcq $-0x1, %rsi
shlq $0x6, %rsi
movq 0x48(%r13), %rdx
movq 0x58(%r13), %r8
subq 0x60(%r13), %r8
sarq $0x3, %r8
addq %rsi, %r8
subq 0x38(%r13), %rdx
sarq $0x3, %rdx
addq %r8, %rdx
je 0x46b52
cmpb $0x0, 0x48(%rcx)
movq %r15, 0x28(%rsp)
movq %r13, 0x20(%rsp)
movq %rdi, 0x18(%rsp)
je 0x46473
movq $0x0, 0x10(%rsp)
jmp 0x46537
cmpb $0x1, 0x68(%rax)
jne 0x46b30
movq 0x8(%rcx), %rax
movq 0x10(%rax), %rax
movl 0x8(%rax), %eax
cmpl $0x2, %eax
je 0x464b1
cmpl $0x1, %eax
jne 0x46b30
leaq 0x2924b(%rip), %rax     # 0x6f6e8
incq (%rax)
movq 0xa0(%rbx), %r14
movq %r15, %rdi
callq 0x272e2
jmp 0x464ca
leaq 0x29260(%rip), %rax     # 0x6f718
incq (%rax)
movq 0xd0(%rbx), %r14
movq %r15, %rdi
callq 0x272e8
addq %r14, %rax
movq %rax, 0x10(%rsp)
movq (%r12), %rax
movq 0x10(%rax), %rax
movl 0x40(%rax), %esi
movq %r15, %rdi
callq 0x27006
movq 0x8(%rsp), %rdi
callq 0x47da6
movq 0x70(%r13), %rax
movq %rax, %rcx
subq 0x50(%r13), %rcx
shrq $0x3, %rcx
cmpq $0x1, %rax
adcq $-0x1, %rcx
shlq $0x6, %rcx
movq 0x48(%r13), %rax
movq 0x58(%r13), %rdx
subq 0x60(%r13), %rdx
sarq $0x3, %rdx
addq %rcx, %rdx
subq 0x38(%r13), %rax
sarq $0x3, %rax
addq %rdx, %rax
je 0x46537
movb $0x1, 0x20(%r13)
movl $0x0, 0x7c(%r13)
movq 0x8(%rsp), %r14
movb $0x0, 0x48(%r14)
movl $0x38, %edi
callq 0x73a0
xorps %xmm0, %xmm0
movaps %xmm0, (%rax)
movaps %xmm0, 0x10(%rax)
movaps %xmm0, 0x20(%rax)
movq $0x0, 0x30(%rax)
movq %rax, (%r14)
movq (%r12), %r13
cmpq %r12, %r13
je 0x465fe
leaq 0x30(%rsp), %rbp
movq 0x8(%rsp), %r15
leaq 0x8(%r15), %r14
movl $0x18, %edi
callq 0x73a0
movq 0x10(%r13), %rcx
movq %rcx, 0x10(%rax)
movq %rax, %rdi
movq %r14, %rsi
callq 0x7060
incq 0x18(%r15)
movq 0x8(%rsp), %rax
movq (%rax), %rdi
addq $0x8, %rdi
movq 0x10(%r13), %rsi
addq $0x38, %rsi
callq 0x2fdf4
movq 0x10(%r13), %rax
movq 0x58(%rax), %rax
movq %rax, 0x30(%rsp)
movq 0x8(%rsp), %rcx
movq (%rcx), %rdi
movq 0x28(%rdi), %rsi
cmpq 0x30(%rdi), %rsi
je 0x465e5
movq %rax, (%rsi)
addq $0x8, %rsi
movq %rsi, 0x28(%rdi)
jmp 0x465f1
addq $0x20, %rdi
movq %rbp, %rdx
callq 0x485c0
movq (%r13), %r13
cmpq %r12, %r13
jne 0x46576
movq (%r12), %rcx
movq 0x10(%rcx), %rax
movl 0x8(%rax), %edx
testl %edx, %edx
je 0x4667d
cmpl $0x1, %edx
movq 0x28(%rsp), %r15
je 0x46648
cmpl $0x2, %edx
movq 0x20(%rsp), %r13
jne 0x46bae
movq 0x10(%r12), %rax
cmpq $0x1, %rax
jne 0x46733
leaq 0x290bd(%rip), %rdx     # 0x6f6f8
incq (%rdx)
movl $0x60d0, %edx           # imm = 0x60D0
jmp 0x46742
cmpl $0x0, 0xa8(%rax)
movq 0x10(%r12), %rsi
movq 0x20(%rsp), %r13
je 0x46852
cmpq $0x1, %rsi
jne 0x46870
leaq 0x29030(%rip), %rax     # 0x6f6a0
incq (%rax)
movl $0x35, %eax
jmp 0x4687f
movq 0x10(%r12), %rax
cmpq $0x1, %rax
movq 0x28(%rsp), %r15
jne 0x4669e
leaq 0x29004(%rip), %rdx     # 0x6f698
incq (%rdx)
movl $0x30, %edx
jmp 0x466ad
leaq 0x2900b(%rip), %rdx     # 0x6f6b0
incq (%rdx)
movl $0x32, %edx
movq 0x20(%rsp), %r13
movq 0x8(%rsp), %rsi
movq (%rsi), %rsi
movq %rdx, (%rsi)
cmpq %r12, %rcx
je 0x466d4
movq 0x28(%rbx,%rax,8), %rdx
movq 0x10(%rcx), %rsi
addq %rdx, 0x30(%rsi)
movq (%rcx), %rcx
jmp 0x466bd
movq 0x70(%r13), %rcx
movq %rcx, %rdx
subq 0x50(%r13), %rdx
shrq $0x3, %rdx
cmpq $0x1, %rcx
adcq $-0x1, %rdx
shlq $0x6, %rdx
movq 0x48(%r13), %rcx
movq 0x58(%r13), %rsi
subq 0x60(%r13), %rsi
sarq $0x3, %rsi
addq %rdx, %rsi
subq 0x38(%r13), %rcx
sarq $0x3, %rcx
addq %rsi, %rcx
je 0x468e0
movq 0x28(%rbx,%rax,8), %rcx
movq 0x10(%rsp), %rsi
addq %rsi, %rcx
movq 0x8(%rsp), %rdx
movq %rcx, 0x60(%rdx)
addq 0x28(%rbx,%rax,8), %rsi
jmp 0x46849
leaq 0x28fce(%rip), %rdx     # 0x6f708
incq (%rdx)
movl $0x60d1, %edx           # imm = 0x60D1
movq 0x8(%rsp), %rsi
movq (%rsi), %rsi
movq %rdx, (%rsi)
cmpq %r12, %rcx
je 0x46767
movq 0xa8(%rbx,%rax,8), %rdx
movq 0x10(%rcx), %rsi
addq %rdx, 0x30(%rsi)
movq (%rcx), %rcx
jmp 0x4674d
movq 0x70(%r13), %rcx
movq %rcx, %rdx
subq 0x50(%r13), %rdx
shrq $0x3, %rdx
cmpq $0x1, %rcx
adcq $-0x1, %rdx
shlq $0x6, %rdx
movq 0x48(%r13), %rcx
movq 0x58(%r13), %rsi
subq 0x60(%r13), %rsi
sarq $0x3, %rsi
addq %rdx, %rsi
subq 0x38(%r13), %rcx
sarq $0x3, %rcx
addq %rsi, %rcx
jne 0x46828
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq %rax, 0x98(%r15)
movl $0x1, (%r13)
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x10(%rsp), %rbp
addq %rbp, %rax
movq 0x10(%r12), %rcx
addq 0xa8(%rbx,%rcx,8), %rax
movq %rax, 0x18(%r13)
callq 0x281b4
movq %rax, %r14
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
addq %rax, %rbp
movq 0x10(%r12), %rax
addq 0xa8(%rbx,%rax,8), %rbp
movq 0x8(%rsp), %rcx
movq %r14, %rdi
movq %rbp, %rsi
movq 0x18(%rsp), %rdx
movl $0x4, %r8d
jmp 0x46957
movq 0xa8(%rbx,%rax,8), %rcx
movq 0x10(%rsp), %rsi
addq %rsi, %rcx
movq 0x8(%rsp), %rdx
movq %rcx, 0x60(%rdx)
addq 0xa8(%rbx,%rax,8), %rsi
addq %rsi, 0x18(%r13)
jmp 0x4695c
cmpq $0x1, %rsi
jne 0x469fe
leaq 0x28e5d(%rip), %rax     # 0x6f6c0
incq (%rax)
movl $0x8010, %eax           # imm = 0x8010
jmp 0x46a0d
leaq 0x28e61(%rip), %rax     # 0x6f6d8
incq (%rax)
movl $0x321, %eax            # imm = 0x321
movq 0x8(%rsp), %rdx
movq (%rdx), %rdx
movq %rax, (%rdx)
cmpq %r12, %rcx
je 0x468a1
movq 0x28(%rbx,%rsi,8), %rax
movq 0x10(%rcx), %rdx
addq %rax, 0x30(%rdx)
movq (%rcx), %rcx
jmp 0x4688a
movq 0x70(%r13), %rax
movq %rax, %rcx
subq 0x50(%r13), %rcx
shrq $0x3, %rcx
cmpq $0x1, %rax
adcq $-0x1, %rcx
shlq $0x6, %rcx
movq 0x48(%r13), %rax
movq 0x58(%r13), %rdx
subq 0x60(%r13), %rdx
sarq $0x3, %rdx
addq %rcx, %rdx
subq 0x38(%r13), %rax
sarq $0x3, %rax
addq %rdx, %rax
jne 0x469da
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq %rax, 0x98(%r15)
movl $0x1, (%r13)
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x10(%rsp), %rbp
addq %rbp, %rax
movq 0x10(%r12), %rcx
addq 0x28(%rbx,%rcx,8), %rax
movq %rax, 0x18(%r13)
callq 0x281b4
movq %rax, %r14
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
addq %rax, %rbp
movq 0x10(%r12), %rax
addq 0x28(%rbx,%rax,8), %rbp
movq 0x8(%rsp), %rcx
movq %r14, %rdi
movq %rbp, %rsi
movq 0x18(%rsp), %rdx
movl $0x1, %r8d
callq 0x285aa
movq 0x58(%r13), %rax
movq 0x68(%r13), %rcx
addq $-0x8, %rcx
cmpq %rcx, %rax
je 0x4697c
movq 0x8(%rsp), %rcx
movq %rcx, (%rax)
addq $0x8, 0x58(%r13)
jmp 0x4698a
leaq 0x28(%r13), %rdi
leaq 0x8(%rsp), %rsi
callq 0x486f6
movq 0x18(%r13), %r14
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rsi
movq 0x8(%rax), %rax
movl 0x14(%rax), %edx
movq %r15, %rdi
callq 0x27e7c
addq %r14, %rax
movq 0x8(%rsp), %rcx
movq %rax, 0x50(%rcx)
cmpq %rax, 0x10(%r13)
jae 0x469be
movq %rax, 0x10(%r13)
movq %rbx, %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x47e24
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x28(%rbx,%rsi,8), %rax
movq 0x10(%rsp), %rdx
addq %rdx, %rax
movq 0x8(%rsp), %rcx
movq %rax, 0x60(%rcx)
addq 0x28(%rbx,%rsi,8), %rdx
addq %rdx, 0x18(%r13)
jmp 0x4695c
leaq 0x28ccb(%rip), %rax     # 0x6f6d0
incq (%rax)
movl $0x8011, %eax           # imm = 0x8011
movq 0x8(%rsp), %rdx
movq (%rdx), %rdx
movq %rax, (%rdx)
cmpq %r12, %rcx
je 0x46a58
movl 0xd8(%rbx), %edi
movq 0x70(%rbx), %r8
xorl %ebp, %ebp
movq 0x10(%rcx), %r9
movl 0x50(%r9), %eax
xorl %edx, %edx
divl %edi
shrl %eax
imulq %r8, %rax
movq 0x30(%r9), %rdx
addq 0x78(%rbx,%rsi,8), %rdx
addq %rax, %rdx
movq %rdx, 0x30(%r9)
addq %rax, %rbp
movq (%rcx), %rcx
cmpq %r12, %rcx
jne 0x46a29
jmp 0x46a5a
xorl %ebp, %ebp
movq 0x70(%r13), %rax
movq %rax, %rcx
subq 0x50(%r13), %rcx
shrq $0x3, %rcx
cmpq $0x1, %rax
adcq $-0x1, %rcx
shlq $0x6, %rcx
movq 0x58(%r13), %rax
subq 0x60(%r13), %rax
movq 0x48(%r13), %rdx
sarq $0x3, %rax
subq 0x38(%r13), %rdx
addq %rcx, %rax
sarq $0x3, %rdx
addq 0x10(%rsp), %rbp
addq %rax, %rdx
jne 0x46b11
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq %rax, 0x98(%r15)
movl $0x2, (%r13)
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x10(%r12), %rcx
addq %rbp, %rax
addq 0x78(%rbx,%rcx,8), %rax
movq %rax, 0x18(%r13)
callq 0x281b4
movq %rax, %r14
callq 0x281b4
movq %rax, %rdi
callq 0x285a6
movq 0x10(%r12), %rcx
addq %rax, %rbp
addq 0x78(%rbx,%rcx,8), %rbp
movq 0x8(%rsp), %rcx
movq %r14, %rdi
movq %rbp, %rsi
movq 0x18(%rsp), %rdx
movl $0x2, %r8d
jmp 0x46957
movq 0x78(%rbx,%rsi,8), %rax
addq %rbp, %rax
movq 0x8(%rsp), %rcx
movq %rax, 0x60(%rcx)
addq 0x78(%rbx,%rsi,8), %rbp
addq %rbp, 0x18(%r13)
jmp 0x4695c
movq 0x284b9(%rip), %rbx     # 0x6eff0
leaq 0xfa6a(%rip), %rsi      # 0x565a8
movq %rbx, %rdi
callq 0x7390
leaq 0x138d6(%rip), %rsi     # 0x5a423
movq %rbx, %rdi
jmp 0x46b8b
movq 0x28497(%rip), %r14     # 0x6eff0
leaq 0xfa48(%rip), %rsi      # 0x565a8
movq %r14, %rdi
callq 0x7390
leaq 0x1387d(%rip), %rsi     # 0x5a3ec
movq %r14, %rdi
callq 0x7390
movl (%rbx), %esi
movq %rax, %rdi
callq 0x74c0
leaq 0x13869(%rip), %rsi     # 0x5a3f1
movq %rax, %rdi
callq 0x7390
movq %rax, %rdi
callq 0x71c0
movq 0x28431(%rip), %rdi     # 0x6efd0
callq 0x7430
movl $0x1, %edi
callq 0x7440
movl $0x10, %edi
callq 0x71d0
movq %rax, %rbx
leaq 0x13883(%rip), %rsi     # 0x5a445
movq %rax, %rdi
callq 0x7680
movq 0x283f7(%rip), %rsi     # 0x6efc8
movq 0x283d8(%rip), %rdx     # 0x6efb0
movq %rbx, %rdi
callq 0x75e0
movq %rax, %r14
movq %rbx, %rdi
callq 0x72c0
movq %r14, %rdi
callq 0x7620
nop