// File: CMU-SAFARI[P]MQSim/src/ssd/GC_and_WL_Unit_Base.cpp
// Function: SSD_Components::GC_and_WL_Unit_Base::handle_transaction_serviced_signal_from_PHY(SSD_Components::NVM_Transaction_Flash*)
void GC_and_WL_Unit_Base::handle_transaction_serviced_signal_from_PHY(NVM_Transaction_Flash* transaction)
	{
		PlaneBookKeepingType* pbke = &(_my_instance->block_manager->plane_manager[transaction->Address.ChannelID][transaction->Address.ChipID][transaction->Address.DieID][transaction->Address.PlaneID]);

		switch (transaction->Source) {
			case Transaction_Source_Type::USERIO:
			case Transaction_Source_Type::MAPPING:
			case Transaction_Source_Type::CACHE:
				switch (transaction->Type)
				{
					case Transaction_Type::READ:
						_my_instance->block_manager->Read_transaction_serviced(transaction->Address);
						break;
					case Transaction_Type::WRITE:
						_my_instance->block_manager->Program_transaction_serviced(transaction->Address);
						break;
					default:
						PRINT_ERROR("Unexpected situation in the GC_and_WL_Unit_Base function!")
				}
				if (_my_instance->block_manager->Block_has_ongoing_gc_wl(transaction->Address)) {
					if (_my_instance->block_manager->Can_execute_gc_wl(transaction->Address)) {
						NVM::FlashMemory::Physical_Page_Address gc_wl_candidate_address(transaction->Address);
						Block_Pool_Slot_Type* block = &pbke->Blocks[transaction->Address.BlockID];
						Stats::Total_gc_executions++;
						_my_instance->tsu->Prepare_for_transaction_submit();
						NVM_Transaction_Flash_ER* gc_wl_erase_tr = new NVM_Transaction_Flash_ER(Transaction_Source_Type::GC_WL, block->Stream_id, gc_wl_candidate_address);
						
						//If there are some valid pages in block, then prepare flash transactions for page movement
						if (block->Current_page_write_index - block->Invalid_page_count > 0) {
							//address_mapping_unit->Lock_physical_block_for_gc(gc_candidate_address);//Lock the block, so no user request can intervene while the GC is progressing
							NVM_Transaction_Flash_RD* gc_wl_read = NULL;
							NVM_Transaction_Flash_WR* gc_wl_write = NULL;
							for (flash_page_ID_type pageID = 0; pageID < block->Current_page_write_index; pageID++) {
								if (_my_instance->block_manager->Is_page_valid(block, pageID)) {
									Stats::Total_page_movements_for_gc++;
									gc_wl_candidate_address.PageID = pageID;
									if (_my_instance->use_copyback) {
										gc_wl_write = new NVM_Transaction_Flash_WR(Transaction_Source_Type::GC_WL, block->Stream_id, _my_instance->sector_no_per_page * SECTOR_SIZE_IN_BYTE,
											NO_LPA, _my_instance->address_mapping_unit->Convert_address_to_ppa(gc_wl_candidate_address), NULL, 0, NULL, 0, INVALID_TIME_STAMP);
										gc_wl_write->ExecutionMode = WriteExecutionModeType::COPYBACK;
										_my_instance->tsu->Submit_transaction(gc_wl_write);
									} else {
										gc_wl_read = new NVM_Transaction_Flash_RD(Transaction_Source_Type::GC_WL, block->Stream_id, _my_instance->sector_no_per_page * SECTOR_SIZE_IN_BYTE,
											NO_LPA, _my_instance->address_mapping_unit->Convert_address_to_ppa(gc_wl_candidate_address), gc_wl_candidate_address, NULL, 0, NULL, 0, INVALID_TIME_STAMP);
										gc_wl_write = new NVM_Transaction_Flash_WR(Transaction_Source_Type::GC_WL, block->Stream_id, _my_instance->sector_no_per_page * SECTOR_SIZE_IN_BYTE,
											NO_LPA, NO_PPA, gc_wl_candidate_address, NULL, 0, gc_wl_read, 0, INVALID_TIME_STAMP);
										gc_wl_write->ExecutionMode = WriteExecutionModeType::SIMPLE;
										gc_wl_write->RelatedErase = gc_wl_erase_tr;
										gc_wl_read->RelatedWrite = gc_wl_write;
										_my_instance->tsu->Submit_transaction(gc_wl_read);//Only the read transaction would be submitted. The Write transaction is submitted when the read transaction is finished and the LPA of the target page is determined
									}
									gc_wl_erase_tr->Page_movement_activities.push_back(gc_wl_write);
								}
							}
						}
						block->Erase_transaction = gc_wl_erase_tr;
						_my_instance->tsu->Schedule();
					}
				}

				return;
		}

		switch (transaction->Type) {
			case Transaction_Type::READ:
			{
				PPA_type ppa;
				MPPN_type mppa;
				page_status_type page_status_bitmap;
				if (pbke->Blocks[transaction->Address.BlockID].Holds_mapping_data) {
					_my_instance->address_mapping_unit->Get_translation_mapping_info_for_gc(transaction->Stream_id, (MVPN_type)transaction->LPA, mppa, page_status_bitmap);
					//There has been no write on the page since GC start, and it is still valid
					if (mppa == transaction->PPA) {
						_my_instance->tsu->Prepare_for_transaction_submit();
						((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite->write_sectors_bitmap = FULL_PROGRAMMED_PAGE;
						((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite->LPA = transaction->LPA;
						((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite->RelatedRead = NULL;
						_my_instance->address_mapping_unit->Allocate_new_page_for_gc(((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite, pbke->Blocks[transaction->Address.BlockID].Holds_mapping_data);
						_my_instance->tsu->Submit_transaction(((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite);
						_my_instance->tsu->Schedule();
					} else {
						PRINT_ERROR("Inconsistency found when moving a page for GC/WL!")
					}
				} else {
					_my_instance->address_mapping_unit->Get_data_mapping_info_for_gc(transaction->Stream_id, transaction->LPA, ppa, page_status_bitmap);
					
					//There has been no write on the page since GC start, and it is still valid
					if (ppa == transaction->PPA) {
						_my_instance->tsu->Prepare_for_transaction_submit();
						((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite->write_sectors_bitmap = page_status_bitmap;
						((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite->LPA = transaction->LPA;
						((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite->RelatedRead = NULL;
						_my_instance->address_mapping_unit->Allocate_new_page_for_gc(((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite, pbke->Blocks[transaction->Address.BlockID].Holds_mapping_data);
						_my_instance->tsu->Submit_transaction(((NVM_Transaction_Flash_RD*)transaction)->RelatedWrite);
						_my_instance->tsu->Schedule();
					} else {
						PRINT_ERROR("Inconsistency found when moving a page for GC/WL!")
					}
				}
				break;
			}
			case Transaction_Type::WRITE:
				if (pbke->Blocks[((NVM_Transaction_Flash_WR*)transaction)->RelatedErase->Address.BlockID].Holds_mapping_data) {
					_my_instance->address_mapping_unit->Remove_barrier_for_accessing_mvpn(transaction->Stream_id, (MVPN_type)transaction->LPA);
					DEBUG(Simulator->Time() << ": MVPN=" << (MVPN_type)transaction->LPA << " unlocked!!");
				} else {
					_my_instance->address_mapping_unit->Remove_barrier_for_accessing_lpa(transaction->Stream_id, transaction->LPA);
					DEBUG(Simulator->Time() << ": LPA=" << (MVPN_type)transaction->LPA << " unlocked!!");
				}
				pbke->Blocks[((NVM_Transaction_Flash_WR*)transaction)->RelatedErase->Address.BlockID].Erase_transaction->Page_movement_activities.remove((NVM_Transaction_Flash_WR*)transaction);
				break;
			case Transaction_Type::ERASE:
				pbke->Ongoing_erase_operations.erase(pbke->Ongoing_erase_operations.find(transaction->Address.BlockID));
				_my_instance->block_manager->Add_erased_block_to_pool(transaction->Address);
				_my_instance->block_manager->GC_WL_finished(transaction->Address);
				if (_my_instance->check_static_wl_required(transaction->Address)) {
					_my_instance->run_static_wearleveling(transaction->Address);
				}
				_my_instance->address_mapping_unit->Start_servicing_writes_for_overfull_plane(transaction->Address);//Must be inovked after above statements since it may lead to flash page consumption for waiting program transactions

				if (_my_instance->Stop_servicing_writes(transaction->Address)) {
					_my_instance->Check_gc_required(pbke->Get_free_block_pool_size(), transaction->Address);
				}
				break;
			} //switch (transaction->Type)
	}

// Assembly:
subq $0x188, %rsp            # imm = 0x188
movq %rdi, 0x180(%rsp)
movq 0x59f62(%rip), %rax     # 0xda708
movq 0x38(%rax), %rax
movq 0x8(%rax), %rax
movq 0x180(%rsp), %rcx
movl 0x38(%rcx), %esi
movl 0x3c(%rcx), %edx
movq (%rax,%rsi,8), %rax
movq (%rax,%rdx,8), %rax
movl 0x40(%rcx), %edx
movq (%rax,%rdx,8), %rax
movl 0x44(%rcx), %ecx
imulq $0xe0, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x178(%rsp)
movq 0x180(%rsp), %rax
movl 0x4(%rax), %eax
movl %eax, 0xac(%rsp)
subl $0x2, %eax
jb 0x8080b
jmp 0x807f9
movl 0xac(%rsp), %eax
subl $0x3, %eax
jne 0x80dfc
jmp 0x8080b
movq 0x180(%rsp), %rax
movl 0x8(%rax), %eax
movl %eax, 0xa8(%rsp)
testl %eax, %eax
je 0x80831
jmp 0x80823
movl 0xa8(%rsp), %eax
subl $0x1, %eax
je 0x8084f
jmp 0x8086d
movq 0x59ed0(%rip), %rax     # 0xda708
movq 0x38(%rax), %rdi
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
callq 0x7ce50
jmp 0x808b8
movq 0x59eb2(%rip), %rax     # 0xda708
movq 0x38(%rax), %rdi
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
callq 0x7cde0
jmp 0x808b8
movq 0x5977c(%rip), %rdi     # 0xd9ff0
leaq 0x2a06d(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x59769(%rip), %rdi     # 0xd9ff0
leaq 0x2d549(%rip), %rsi     # 0xaddd7
callq 0x8440
movq %rax, %rdi
movq 0x596bb(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x59727(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq 0x59e49(%rip), %rax     # 0xda708
movq 0x38(%rax), %rdi
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
callq 0x7cb90
testb $0x1, %al
jne 0x808dd
jmp 0x80df7
movq 0x59e24(%rip), %rax     # 0xda708
movq 0x38(%rax), %rdi
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
callq 0x7cc00
testb $0x1, %al
jne 0x80902
jmp 0x80df5
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
leaq 0x160(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x5e380
movq 0x178(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x180(%rsp), %rcx
movl 0x48(%rcx), %ecx
shlq $0x6, %rcx
addq %rcx, %rax
movq %rax, 0x158(%rsp)
leaq 0x5aecc(%rip), %rax     # 0xdb81c
movl (%rax), %ecx
incl %ecx
movl %ecx, (%rax)
movq 0x59dab(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
callq 0x59940
movl $0x98, %edi
callq 0x8450
movq 0x98(%rsp), %rcx
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0xa0(%rsp)
movq 0x158(%rsp), %rax
movzwl 0x20(%rax), %edx
movl $0x2, %esi
callq 0x95e40
jmp 0x8099e
movq 0xa0(%rsp), %rax
movq %rax, 0x150(%rsp)
movq 0x158(%rsp), %rax
movl 0x4(%rax), %eax
movq 0x158(%rsp), %rcx
subl 0xc(%rcx), %eax
cmpl $0x0, %eax
jbe 0x80dd0
movq $0x0, 0x138(%rsp)
movq $0x0, 0x130(%rsp)
movl $0x0, 0x12c(%rsp)
movl 0x12c(%rsp), %eax
movq 0x158(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jae 0x80dce
movq 0x59cf9(%rip), %rax     # 0xda708
movq 0x38(%rax), %rdi
movq 0x158(%rsp), %rsi
movl 0x12c(%rsp), %edx
callq 0x7cfa0
testb $0x1, %al
jne 0x80a30
jmp 0x80db6
leaq 0x5b1e9(%rip), %rax     # 0xdbc20
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x5b1dd(%rip), %rax     # 0xdbc20
movl %ecx, (%rax)
movl 0x12c(%rsp), %eax
movl %eax, 0x174(%rsp)
movq 0x59cae(%rip), %rax     # 0xda708
testb $0x1, 0x64(%rax)
je 0x80bad
movl $0xb0, %edi
callq 0x8450
movq %rax, 0x80(%rsp)
movq 0x158(%rsp), %rax
movw 0x20(%rax), %ax
movw %ax, 0x8a(%rsp)
movq 0x59c77(%rip), %rax     # 0xda708
movl 0x10c(%rax), %ecx
shll $0x9, %ecx
movl %ecx, 0x8c(%rsp)
movq 0x30(%rax), %rdi
movq (%rdi), %rax
movq 0x90(%rax), %rax
leaq 0x160(%rsp), %rsi
callq *%rax
movq %rax, 0x90(%rsp)
jmp 0x80ac3
movq 0x90(%rsp), %r9
movl 0x8c(%rsp), %ecx
movq 0x80(%rsp), %rdi
movw 0x8a(%rsp), %ax
movq %rsp, %rdx
movq $-0x1, 0x20(%rdx)
movq $0x0, 0x18(%rdx)
movq $0x0, 0x10(%rdx)
movq $0x0, 0x8(%rdx)
movq $0x0, (%rdx)
movzwl %ax, %edx
movl $0x2, %esi
movq $-0x1, %r8
callq 0x96320
jmp 0x80b22
movq 0x80(%rsp), %rax
movq %rax, 0x130(%rsp)
movq 0x130(%rsp), %rax
movl $0x1, 0xa8(%rax)
movq 0x59bbd(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
movq 0x130(%rsp), %rsi
callq 0x59980
jmp 0x80d9a
movq 0xa0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
callq 0x8410
jmp 0x813df
movq 0x80(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
callq 0x8410
jmp 0x813df
movl $0xa0, %edi
callq 0x8450
movq %rax, 0x68(%rsp)
movq 0x158(%rsp), %rax
movw 0x20(%rax), %ax
movw %ax, 0x72(%rsp)
movq 0x59b34(%rip), %rax     # 0xda708
movl 0x10c(%rax), %ecx
shll $0x9, %ecx
movl %ecx, 0x74(%rsp)
movq 0x30(%rax), %rdi
movq (%rdi), %rax
movq 0x90(%rax), %rax
leaq 0x160(%rsp), %rsi
callq *%rax
movq %rax, 0x78(%rsp)
jmp 0x80c00
movq 0x78(%rsp), %r9
movl 0x74(%rsp), %ecx
movq 0x68(%rsp), %rdi
movw 0x72(%rsp), %ax
movq %rsp, %rdx
leaq 0x160(%rsp), %rsi
movq %rsi, (%rdx)
movq $-0x1, 0x28(%rdx)
movq $0x0, 0x20(%rdx)
movq $0x0, 0x18(%rdx)
movq $0x0, 0x10(%rdx)
movq $0x0, 0x8(%rdx)
movzwl %ax, %edx
movl $0x2, %esi
movq $-0x1, %r8
callq 0x95fe0
jmp 0x80c5f
movq 0x68(%rsp), %rax
movq %rax, 0x138(%rsp)
movl $0xb0, %edi
callq 0x8450
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x60(%rsp)
movq 0x158(%rsp), %rax
movzwl 0x20(%rax), %edx
movq 0x59a74(%rip), %rax     # 0xda708
movl 0x10c(%rax), %ecx
shll $0x9, %ecx
movq 0x138(%rsp), %rsi
movq %rsp, %rax
movq %rsi, 0x18(%rax)
leaq 0x160(%rsp), %rsi
movq %rsi, (%rax)
movq $-0x1, 0x28(%rax)
movq $0x0, 0x20(%rax)
movq $0x0, 0x10(%rax)
movq $0x0, 0x8(%rax)
movl $0x2, %esi
movq $-0x1, %r9
movq %r9, %r8
callq 0x96240
jmp 0x80ced
movq 0x60(%rsp), %rax
movq %rax, 0x130(%rsp)
movq 0x130(%rsp), %rax
movl $0x0, 0xa8(%rax)
movq 0x150(%rsp), %rcx
movq 0x130(%rsp), %rax
movq %rcx, 0x90(%rax)
movq 0x130(%rsp), %rcx
movq 0x138(%rsp), %rax
movq %rcx, 0x88(%rax)
movq 0x599c7(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
movq 0x138(%rsp), %rsi
callq 0x59980
jmp 0x80d9a
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
callq 0x8410
jmp 0x813df
movq 0x60(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
callq 0x8410
jmp 0x813df
movq 0x150(%rsp), %rdi
addq $0x80, %rdi
leaq 0x130(%rsp), %rsi
callq 0x81ce0
jmp 0x80db8
movl 0x12c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x12c(%rsp)
jmp 0x809f0
jmp 0x80dd0
movq 0x150(%rsp), %rcx
movq 0x158(%rsp), %rax
movq %rcx, 0x28(%rax)
movq 0x5991d(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
movq (%rdi), %rax
callq *0x30(%rax)
jmp 0x80df7
jmp 0x813d7
movq 0x180(%rsp), %rax
movl 0x8(%rax), %eax
movl %eax, 0x5c(%rsp)
testl %eax, %eax
je 0x80e32
jmp 0x80e11
movl 0x5c(%rsp), %eax
subl $0x1, %eax
je 0x81163
jmp 0x80e20
movl 0x5c(%rsp), %eax
subl $0x2, %eax
je 0x81240
jmp 0x813d7
movq 0x178(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x180(%rsp), %rcx
movl 0x48(%rcx), %ecx
shlq $0x6, %rcx
addq %rcx, %rax
testb $0x1, 0x22(%rax)
je 0x80fdc
movq 0x598a7(%rip), %rax     # 0xda708
movq 0x30(%rax), %rdi
movq 0x180(%rsp), %rax
movw (%rax), %si
movq 0x180(%rsp), %rax
movq 0x58(%rax), %rax
movl %eax, %edx
movq (%rdi), %rax
leaq 0x11c(%rsp), %rcx
leaq 0x110(%rsp), %r8
movzwl %si, %esi
callq *0x70(%rax)
movl 0x11c(%rsp), %eax
movq 0x180(%rsp), %rcx
cmpq 0x60(%rcx), %rax
jne 0x80f8c
movq 0x59851(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
callq 0x59940
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rax
movq $-0x1, 0x98(%rax)
movq 0x180(%rsp), %rax
movq 0x58(%rax), %rcx
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rax
movq %rcx, 0x58(%rax)
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rax
movq $0x0, 0x88(%rax)
movq 0x597ee(%rip), %rax     # 0xda708
movq 0x30(%rax), %rdi
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rsi
movq 0x178(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x180(%rsp), %rcx
movl 0x48(%rcx), %ecx
shlq $0x6, %rcx
addq %rcx, %rax
movb 0x22(%rax), %cl
movq (%rdi), %rax
andb $0x1, %cl
movzbl %cl, %edx
callq *0x78(%rax)
movq 0x597a7(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rsi
callq 0x59980
movq 0x59788(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
movq (%rdi), %rax
callq *0x30(%rax)
jmp 0x80fd7
movq 0x5905d(%rip), %rdi     # 0xd9ff0
leaq 0x2994e(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x5904a(%rip), %rdi     # 0xd9ff0
leaq 0x2ce64(%rip), %rsi     # 0xade11
callq 0x8440
movq %rax, %rdi
movq 0x58f9c(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x59008(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
jmp 0x8115e
movq 0x59725(%rip), %rax     # 0xda708
movq 0x30(%rax), %rdi
movq 0x180(%rsp), %rax
movw (%rax), %si
movq 0x180(%rsp), %rax
movq 0x58(%rax), %rdx
movq (%rdi), %rax
leaq 0x120(%rsp), %rcx
leaq 0x110(%rsp), %r8
movzwl %si, %esi
callq *0x68(%rax)
movq 0x120(%rsp), %rax
movq 0x180(%rsp), %rcx
cmpq 0x60(%rcx), %rax
jne 0x81111
movq 0x596d0(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
callq 0x59940
movq 0x110(%rsp), %rcx
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rax
movq %rcx, 0x98(%rax)
movq 0x180(%rsp), %rax
movq 0x58(%rax), %rcx
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rax
movq %rcx, 0x58(%rax)
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rax
movq $0x0, 0x88(%rax)
movq 0x59669(%rip), %rax     # 0xda708
movq 0x30(%rax), %rdi
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rsi
movq 0x178(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x180(%rsp), %rcx
movl 0x48(%rcx), %ecx
shlq $0x6, %rcx
addq %rcx, %rax
movb 0x22(%rax), %cl
movq (%rdi), %rax
andb $0x1, %cl
movzbl %cl, %edx
callq *0x78(%rax)
movq 0x59622(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
movq 0x180(%rsp), %rax
movq 0x88(%rax), %rsi
callq 0x59980
movq 0x59603(%rip), %rax     # 0xda708
movq 0x40(%rax), %rdi
movq (%rdi), %rax
callq *0x30(%rax)
jmp 0x8115c
movq 0x58ed8(%rip), %rdi     # 0xd9ff0
leaq 0x297c9(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x58ec5(%rip), %rdi     # 0xd9ff0
leaq 0x2ccdf(%rip), %rsi     # 0xade11
callq 0x8440
movq %rax, %rdi
movq 0x58e17(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x58e83(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
jmp 0x8115e
jmp 0x813d7
movq 0x178(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x180(%rsp), %rcx
movq 0x90(%rcx), %rcx
movl 0x48(%rcx), %ecx
shlq $0x6, %rcx
addq %rcx, %rax
testb $0x1, 0x22(%rax)
je 0x811c0
movq 0x59573(%rip), %rax     # 0xda708
movq 0x30(%rax), %rdi
movq 0x180(%rsp), %rax
movw (%rax), %cx
movq 0x180(%rsp), %rax
movq 0x58(%rax), %rax
movl %eax, %edx
movq (%rdi), %rax
movzwl %cx, %esi
callq *0xb8(%rax)
jmp 0x811ee
movq 0x59541(%rip), %rax     # 0xda708
movq 0x30(%rax), %rdi
movq 0x180(%rsp), %rax
movw (%rax), %cx
movq 0x180(%rsp), %rax
movq 0x58(%rax), %rdx
movq (%rdi), %rax
movzwl %cx, %esi
callq *0xb0(%rax)
movq 0x178(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x180(%rsp), %rcx
movq 0x90(%rcx), %rcx
movl 0x48(%rcx), %ecx
shlq $0x6, %rcx
addq %rcx, %rax
movq 0x28(%rax), %rdi
addq $0x80, %rdi
movq 0x180(%rsp), %rax
movq %rax, 0x108(%rsp)
leaq 0x108(%rsp), %rsi
callq 0x81d20
jmp 0x813d7
movq 0x178(%rsp), %rax
addq $0xb0, %rax
movq %rax, 0x48(%rsp)
movq 0x178(%rsp), %rdi
addq $0xb0, %rdi
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
addq $0x10, %rsi
callq 0x5a300
movq 0x48(%rsp), %rdi
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rsi
callq 0x5ee40
movq %rax, 0xf8(%rsp)
movq 0x59468(%rip), %rax     # 0xda708
movq 0x38(%rax), %rdi
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
movq (%rdi), %rax
callq *0x40(%rax)
movq 0x5944b(%rip), %rax     # 0xda708
movq 0x38(%rax), %rdi
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
callq 0x7cf30
movq 0x5942f(%rip), %rax     # 0xda708
movq %rax, 0x50(%rsp)
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
leaq 0xe0(%rsp), %rdi
callq 0x5e380
movq 0x50(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x81e20
testb $0x1, %al
jne 0x8130f
jmp 0x81346
movq 0x593f2(%rip), %rax     # 0xda708
movq %rax, 0x40(%rsp)
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
leaq 0xc8(%rsp), %rdi
callq 0x5e380
movq 0x40(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0x813f0
movq 0x593bb(%rip), %rax     # 0xda708
movq 0x30(%rax), %rax
movq %rax, 0x38(%rsp)
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
leaq 0xb0(%rsp), %rdi
callq 0x5e380
movq 0x38(%rsp), %rdi
movq (%rdi), %rax
leaq 0xb0(%rsp), %rsi
callq *0xc0(%rax)
movq 0x5937c(%rip), %rdi     # 0xda708
movq 0x180(%rsp), %rsi
addq $0x38, %rsi
callq 0x81a30
testb $0x1, %al
jne 0x813a3
jmp 0x813d5
movq 0x5935e(%rip), %rax     # 0xda708
movq %rax, 0x30(%rsp)
movq 0x178(%rsp), %rdi
callq 0x7c950
movq 0x30(%rsp), %rdi
movl %eax, %esi
movq 0x180(%rsp), %rdx
addq $0x38, %rdx
movq (%rdi), %rax
callq *0x28(%rax)
jmp 0x813d7
addq $0x188, %rsp            # imm = 0x188
retq
movq 0x148(%rsp), %rdi
callq 0x8770
nopl (%rax)