// File: /workspace/github_cpp_makefile_star2_O3/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), %rcx
shlq $0x7, %rdx
movl 0x40(%rax), %esi
imulq $0x68, %rsi, %rbp
addq 0x8(%rcx,%rdx), %rbp
leaq (%rcx,%rdx), %r13
movq %rbp, 0x8(%rsp)
cmpl $0x0, 0x14(%rbx)
jne 0x459c2
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 0x460a6
cmpb $0x0, 0x48(%rbp)
movq %r13, 0x20(%rsp)
movq %rdi, 0x18(%rsp)
je 0x459e0
movq $0x0, 0x10(%rsp)
jmp 0x45aa2
cmpb $0x1, 0x68(%rax)
jne 0x46084
movq 0x8(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x8(%rax), %eax
cmpl $0x2, %eax
je 0x45a1e
cmpl $0x1, %eax
jne 0x46084
leaq 0x29cde(%rip), %rax     # 0x6f6e8
incq (%rax)
movq 0xa0(%rbx), %r14
movq %r15, %rdi
callq 0x2714a
jmp 0x45a37
leaq 0x29cf3(%rip), %rax     # 0x6f718
incq (%rax)
movq 0xd0(%rbx), %r14
movq %r15, %rdi
callq 0x27150
addq %r14, %rax
movq %rax, 0x10(%rsp)
movq (%r12), %rax
movq 0x10(%rax), %rax
movl 0x40(%rax), %esi
movq %r15, %rdi
callq 0x26e6e
movq %rbp, %rdi
callq 0x47342
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 0x45aa2
movb $0x1, 0x20(%r13)
movl $0x0, 0x7c(%r13)
movb $0x0, 0x48(%rbp)
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, (%rbp)
movq (%r12), %r13
cmpq %r12, %r13
je 0x45b72
movq %r15, 0x28(%rsp)
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 0x2f7b8
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 0x45b50
movq %rax, (%rsi)
addq $0x8, %rsi
movq %rsi, 0x28(%rdi)
jmp 0x45b5c
addq $0x20, %rdi
movq %rbp, %rdx
callq 0x47b64
movq (%r13), %r13
cmpq %r12, %r13
jne 0x45ae1
movq (%r12), %r13
movq 0x28(%rsp), %r15
movq 0x10(%r13), %rax
movl 0x8(%rax), %ecx
testl %ecx, %ecx
je 0x45c08
cmpl $0x1, %ecx
je 0x45baf
cmpl $0x2, %ecx
jne 0x46102
movq 0x10(%r12), %rax
xorl %edx, %edx
cmpq $0x1, %rax
sete %cl
jne 0x45d8e
leaq 0x29b4e(%rip), %rsi     # 0x6f6f8
jmp 0x45d95
cmpl $0x0, 0xa8(%rax)
movq 0x10(%r12), %rcx
je 0x45eb2
cmpq $0x1, %rcx
leaq 0x29b0c(%rip), %rax     # 0x6f6d8
cmoveq 0x293dc(%rip), %rax     # 0x6efb0
movl $0x35, %edx
movl $0x321, %esi            # imm = 0x321
cmoveq %rdx, %rsi
incq (%rax)
movq 0x8(%rsp), %rax
movq (%rax), %rdx
movq %rsi, (%rdx)
cmpq %r12, %r13
je 0x45c21
movq 0x28(%rbx,%rcx,8), %rdx
movq 0x10(%r13), %rsi
addq %rdx, 0x30(%rsi)
movq (%r13), %r13
jmp 0x45bf0
movq 0x10(%r12), %rax
xorl %ecx, %ecx
cmpq $0x1, %rax
setne %dl
jne 0x45c80
leaq 0x29a79(%rip), %rsi     # 0x6f698
jmp 0x45c87
movq 0x20(%rsp), %r13
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), %rdi
subq 0x60(%r13), %rdi
sarq $0x3, %rdi
addq %rsi, %rdi
subq 0x38(%r13), %rdx
sarq $0x3, %rdx
addq %rdi, %rdx
je 0x45cf7
movq 0x28(%rbx,%rcx,8), %rdx
movq 0x10(%rsp), %rsi
addq %rsi, %rdx
movq %rdx, 0x60(%rax)
addq 0x28(%rbx,%rcx,8), %rsi
jmp 0x45ea9
leaq 0x29a29(%rip), %rsi     # 0x6f6b0
movb %dl, %cl
leaq 0x30(,%rcx,2), %rdx
incq (%rsi)
movq 0x8(%rsp), %rcx
movq (%rcx), %rsi
movq %rdx, (%rsi)
cmpq %r12, %r13
je 0x45cb7
movq 0x28(%rbx,%rax,8), %rdx
movq 0x10(%r13), %rsi
addq %rdx, 0x30(%rsi)
movq (%r13), %r13
jmp 0x45c9f
movq 0x20(%rsp), %r13
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), %rdi
subq 0x60(%r13), %rdi
sarq $0x3, %rdi
addq %rsi, %rdi
subq 0x38(%r13), %rdx
sarq $0x3, %rdx
addq %rdi, %rdx
jne 0x45d73
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq %rax, 0x98(%r15)
movl $0x1, (%r13)
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq 0x10(%rsp), %rbp
addq %rbp, %rax
movq 0x10(%r12), %rcx
addq 0x28(%rbx,%rcx,8), %rax
movq %rax, 0x18(%r13)
callq 0x28018
movq %rax, %r14
callq 0x28018
movq %rax, %rdi
callq 0x2841a
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
jmp 0x45fe1
movq 0x28(%rbx,%rax,8), %rdx
movq 0x10(%rsp), %rsi
addq %rsi, %rdx
movq %rdx, 0x60(%rcx)
addq 0x28(%rbx,%rax,8), %rsi
jmp 0x45ea9
leaq 0x29973(%rip), %rsi     # 0x6f708
movb %cl, %dl
xorq $0x60d1, %rdx           # imm = 0x60D1
incq (%rsi)
movq 0x8(%rsp), %rcx
movq (%rcx), %rsi
movq %rdx, (%rsi)
cmpq %r12, %r13
je 0x45dc7
movq 0xa8(%rbx,%rax,8), %rdx
movq 0x10(%r13), %rsi
addq %rdx, 0x30(%rsi)
movq (%r13), %r13
jmp 0x45dac
movq 0x20(%rsp), %r13
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), %rdi
subq 0x60(%r13), %rdi
sarq $0x3, %rdi
addq %rsi, %rdi
subq 0x38(%r13), %rdx
sarq $0x3, %rdx
addq %rdi, %rdx
jne 0x45e8d
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq %rax, 0x98(%r15)
movl $0x1, (%r13)
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq 0x10(%rsp), %rbp
addq %rbp, %rax
movq 0x10(%r12), %rcx
addq 0xa8(%rbx,%rcx,8), %rax
movq %rax, 0x18(%r13)
callq 0x28018
movq %rax, %r14
callq 0x28018
movq %rax, %rdi
callq 0x2841a
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 0x45fe1
movq 0xa8(%rbx,%rax,8), %rdx
movq 0x10(%rsp), %rsi
addq %rsi, %rdx
movq %rdx, 0x60(%rcx)
addq 0xa8(%rbx,%rax,8), %rsi
addq %rsi, 0x18(%r13)
jmp 0x45fe6
xorl %eax, %eax
cmpq $0x1, %rcx
sete %dl
jne 0x45ec6
leaq 0x297fc(%rip), %rsi     # 0x6f6c0
jmp 0x45ecd
leaq 0x29803(%rip), %rsi     # 0x6f6d0
movb %dl, %al
xorq $0x8011, %rax           # imm = 0x8011
incq (%rsi)
movq 0x8(%rsp), %rsi
movq (%rsi), %rdx
movq %rax, (%rdx)
cmpq %r12, %r13
je 0x45f24
movl 0xd8(%rbx), %edi
movq 0x70(%rbx), %r8
xorl %ebp, %ebp
movq 0x10(%r13), %r9
movl 0x50(%r9), %eax
xorl %edx, %edx
divl %edi
shrl %eax
imulq %r8, %rax
movq 0x30(%r9), %rdx
addq 0x78(%rbx,%rcx,8), %rdx
addq %rax, %rdx
movq %rdx, 0x30(%r9)
addq %rax, %rbp
movq (%r13), %r13
cmpq %r12, %r13
jne 0x45ef4
jmp 0x45f26
xorl %ebp, %ebp
movq 0x20(%rsp), %r13
movq 0x70(%r13), %rax
movq %rax, %rdx
subq 0x50(%r13), %rdx
shrq $0x3, %rdx
cmpq $0x1, %rax
adcq $-0x1, %rdx
shlq $0x6, %rdx
movq 0x48(%r13), %rax
movq 0x58(%r13), %rdi
subq 0x60(%r13), %rdi
sarq $0x3, %rdi
addq %rdx, %rdi
subq 0x38(%r13), %rax
sarq $0x3, %rax
addq %rdi, %rax
jne 0x46065
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq %rax, 0x98(%r15)
movl $0x2, (%r13)
callq 0x28018
movq %rax, %rdi
callq 0x2841a
movq 0x10(%r12), %rcx
addq 0x10(%rsp), %rbp
addq %rbp, %rax
addq 0x78(%rbx,%rcx,8), %rax
movq %rax, 0x18(%r13)
callq 0x28018
movq %rax, %r14
callq 0x28018
movq %rax, %rdi
callq 0x2841a
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
callq 0x2841e
movq 0x58(%r13), %rcx
movq 0x68(%r13), %rax
addq $-0x8, %rax
cmpq %rax, %rcx
je 0x46006
movq 0x8(%rsp), %rax
movq %rax, (%rcx)
addq $0x8, 0x58(%r13)
jmp 0x4601a
leaq 0x28(%r13), %rdi
leaq 0x8(%rsp), %r14
movq %r14, %rsi
callq 0x47c9a
movq (%r14), %rax
movq 0x18(%r13), %r14
movq (%rax), %rax
movq (%rax), %rsi
movq 0x8(%rax), %rax
movl 0x14(%rax), %edx
movq %r15, %rdi
callq 0x27ce2
addq %r14, %rax
movq 0x8(%rsp), %rcx
movq %rax, 0x50(%rcx)
cmpq %rax, 0x10(%r13)
jae 0x46049
movq %rax, 0x10(%r13)
movq %rbx, %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x473c0
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
addq 0x10(%rsp), %rbp
movq 0x78(%rbx,%rcx,8), %rax
addq %rbp, %rax
movq %rax, 0x60(%rsi)
addq 0x78(%rbx,%rcx,8), %rbp
addq %rbp, 0x18(%r13)
jmp 0x45fe6
movq 0x28f65(%rip), %rbx     # 0x6eff0
leaq 0x10516(%rip), %rsi     # 0x565a8
movq %rbx, %rdi
callq 0x7390
leaq 0x14382(%rip), %rsi     # 0x5a423
movq %rbx, %rdi
jmp 0x460df
movq 0x28f43(%rip), %r14     # 0x6eff0
leaq 0x104f4(%rip), %rsi     # 0x565a8
movq %r14, %rdi
callq 0x7390
leaq 0x14329(%rip), %rsi     # 0x5a3ec
movq %r14, %rdi
callq 0x7390
movl (%rbx), %esi
movq %rax, %rdi
callq 0x74c0
leaq 0x14315(%rip), %rsi     # 0x5a3f1
movq %rax, %rdi
callq 0x7390
movq %rax, %rdi
callq 0x71c0
movq 0x28edd(%rip), %rdi     # 0x6efd0
callq 0x7430
movl $0x1, %edi
callq 0x7440
movl $0x10, %edi
callq 0x71d0
movq %rax, %rbx
leaq 0x1432f(%rip), %rsi     # 0x5a445
movq %rax, %rdi
callq 0x7680
movq 0x28ea3(%rip), %rsi     # 0x6efc8
movq 0x28e7c(%rip), %rdx     # 0x6efa8
movq %rbx, %rdi
callq 0x75e0
movq %rax, %r14
movq %rbx, %rdi
callq 0x72c0
movq %r14, %rdi
callq 0x7620
nop