// File: CMU-SAFARI[P]MQSim/src/ssd/Address_Mapping_Unit_Page_Level.cpp
// Function: SSD_Components::Address_Mapping_Unit_Page_Level::Remove_barrier_for_accessing_mvpn(unsigned short, unsigned int)
inline void Address_Mapping_Unit_Page_Level::Remove_barrier_for_accessing_mvpn(stream_id_type stream_id, MVPN_type mvpn)
	{
		auto itr = domains[stream_id]->Locked_MVPNs.find(mvpn);
		if (itr == domains[stream_id]->Locked_MVPNs.end()) {
			PRINT_ERROR("Illegal operation: Unlocking an MVPN that has not been locked!");
		}
		domains[stream_id]->Locked_MVPNs.erase(itr);

		//If there are read requests waiting behind the barrier, then MQSim assumes they can be serviced with the actual page data that is accessed during GC execution
		if (domains[stream_id]->MVPN_read_transactions_waiting_behind_barrier.find(mvpn) != domains[stream_id]->MVPN_read_transactions_waiting_behind_barrier.end()) {
			domains[stream_id]->MVPN_read_transactions_waiting_behind_barrier.erase(mvpn);
			PPA_type ppn = domains[stream_id]->GlobalTranslationDirectory[mvpn].MPPN;
			if (ppn == NO_MPPN) {
				PRINT_ERROR("Reading an invalid physical flash page address in function generate_flash_read_request_for_mapping_data!")
			}

			NVM_Transaction_Flash_RD* readTR = new NVM_Transaction_Flash_RD(Transaction_Source_Type::MAPPING, stream_id,
					SECTOR_SIZE_IN_BYTE, NO_LPA, NO_PPA, NULL, mvpn, ((page_status_type)0x1) << sector_no_per_page, CurrentTimeStamp);
			Convert_ppa_to_address(ppn, readTR->Address);
			readTR->PPA = ppn;
			Stats::Total_flash_reads_for_mapping++;
			Stats::Total_flash_reads_for_mapping_per_stream[stream_id]++;

			handle_transaction_serviced_signal_from_PHY(readTR);
			
			delete readTR;
		}

		//If there are write requests waiting behind the barrier, then MQSim assumes they can be serviced with the actual page data that is accessed during GC execution. This may not be 100% true for all write requests, but, to avoid more complexity in the simulation, we accept this assumption.
		if (domains[stream_id]->MVPN_write_transaction_waiting_behind_barrier.find(mvpn) != domains[stream_id]->MVPN_write_transaction_waiting_behind_barrier.end()) {
			domains[stream_id]->MVPN_write_transaction_waiting_behind_barrier.erase(mvpn);
			//Writing back all dirty CMT entries that fall into the same translation virtual page (MVPN)
			unsigned int read_size = 0;
			page_status_type readSectorsBitmap = 0;
			LPA_type start_lpn = get_start_LPN_in_MVP(mvpn);
			LPA_type end_lpn = get_end_LPN_in_MVP(mvpn);
			for (LPA_type lpn_itr = start_lpn; lpn_itr <= end_lpn; lpn_itr++) {
				if (domains[stream_id]->CMT->Exists(stream_id, lpn_itr)) {
					if (domains[stream_id]->CMT->Is_dirty(stream_id, lpn_itr)) {
						domains[stream_id]->CMT->Make_clean(stream_id, lpn_itr);
					} else {
						page_status_type bitlocation = (((page_status_type)0x1) << (((lpn_itr - start_lpn) * GTD_entry_size) / SECTOR_SIZE_IN_BYTE));
						if ((readSectorsBitmap & bitlocation) == 0) {
							readSectorsBitmap |= bitlocation;
							read_size += SECTOR_SIZE_IN_BYTE;
						}
					}
				}
			}

			//Read the unchaged mapping entries from flash to merge them with updated parts of MVPN
			MPPN_type mppn = domains[stream_id]->GlobalTranslationDirectory[mvpn].MPPN;
			NVM_Transaction_Flash_WR* writeTR = new NVM_Transaction_Flash_WR(Transaction_Source_Type::MAPPING, stream_id, SECTOR_SIZE_IN_BYTE * sector_no_per_page,
				mvpn, mppn, NULL, mvpn, NULL, (((page_status_type)0x1) << sector_no_per_page) - 1, CurrentTimeStamp);

			Stats::Total_flash_reads_for_mapping++;
			Stats::Total_flash_writes_for_mapping++;
			Stats::Total_flash_reads_for_mapping_per_stream[stream_id]++;
			Stats::Total_flash_writes_for_mapping_per_stream[stream_id]++;

			handle_transaction_serviced_signal_from_PHY(writeTR);

			delete writeTR;
		}
	}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movw %si, %ax
movq %rdi, 0x160(%rsp)
movw %ax, 0x15e(%rsp)
movl %edx, 0x158(%rsp)
movq 0x160(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x118, %rdi            # imm = 0x118
leaq 0x158(%rsp), %rsi
callq 0x5a300
movq %rax, %rcx
movq 0xb0(%rsp), %rax
movq %rcx, 0x150(%rsp)
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x118, %rdi            # imm = 0x118
callq 0x5a340
movq %rax, 0x148(%rsp)
leaq 0x150(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0x5dec0
testb $0x1, %al
jne 0x5b4ad
jmp 0x5b4f8
movq 0x7eb3c(%rip), %rdi     # 0xd9ff0
leaq 0x4f42d(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x7eb29(%rip), %rdi     # 0xd9ff0
leaq 0x519b4(%rip), %rsi     # 0xace82
callq 0x8440
movq %rax, %rdi
movq 0x7ea7b(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x7eae7(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x118, %rdi            # imm = 0x118
movq 0x150(%rsp), %rax
movq %rax, 0x140(%rsp)
movq 0x140(%rsp), %rsi
callq 0x5ee40
movq %rax, %rcx
movq 0xb0(%rsp), %rax
movq %rcx, 0x138(%rsp)
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x1a8, %rdi            # imm = 0x1A8
leaq 0x158(%rsp), %rsi
callq 0x5a300
movq %rax, %rcx
movq 0xb0(%rsp), %rax
movq %rcx, 0x130(%rsp)
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x1a8, %rdi            # imm = 0x1A8
callq 0x5a340
movq %rax, 0x128(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0x5a2e0
testb $0x1, %al
jne 0x5b5c9
jmp 0x5b830
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x1a8, %rdi            # imm = 0x1A8
leaq 0x158(%rsp), %rsi
callq 0x5d810
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq (%rax), %rax
movl 0x158(%rsp), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
movq %rax, 0x120(%rsp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq %rax, 0x120(%rsp)
jne 0x5b688
movq 0x7e9ac(%rip), %rdi     # 0xd9ff0
leaq 0x4f29d(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x7e999(%rip), %rdi     # 0xd9ff0
leaq 0x5162d(%rip), %rsi     # 0xacc8b
callq 0x8440
movq %rax, %rdi
movq 0x7e8eb(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x7e957(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movl $0xa0, %edi
callq 0x8450
movq %rax, %rcx
movq 0xb0(%rsp), %rax
movq %rcx, 0x88(%rsp)
movw 0x15e(%rsp), %cx
movw %cx, 0x96(%rsp)
movl 0x158(%rsp), %ecx
movq %rcx, 0x98(%rsp)
movb 0x7c(%rax), %cl
movl $0x1, %eax
shlq %cl, %rax
movq %rax, 0xa0(%rsp)
callq 0x46500
movq %rax, 0xa8(%rsp)
jmp 0x5b6e6
movq 0xa8(%rsp), %rdi
callq 0x46c50
movq %rax, 0x80(%rsp)
jmp 0x5b6fd
movq 0x88(%rsp), %rdi
movw 0x96(%rsp), %ax
movq 0x98(%rsp), %rdx
movq 0xa0(%rsp), %rsi
movq 0x80(%rsp), %r8
movq %rsp, %rcx
movq %r8, 0x18(%rcx)
movq %rsi, 0x10(%rcx)
movq %rdx, 0x8(%rcx)
movq $0x0, (%rcx)
movzwl %ax, %edx
movl $0x3, %esi
movl $0x200, %ecx            # imm = 0x200
movq $-0x1, %r9
movq %r9, %r8
callq 0x96180
jmp 0x5b759
movq 0xb0(%rsp), %rdi
movq 0x88(%rsp), %rax
movq %rax, 0x118(%rsp)
movq 0x120(%rsp), %rsi
movq 0x118(%rsp), %rdx
addq $0x38, %rdx
movq (%rdi), %rax
callq *0x88(%rax)
movq 0x120(%rsp), %rcx
movq 0x118(%rsp), %rax
movq %rcx, 0x60(%rax)
leaq 0x7f037(%rip), %rax     # 0xda7e0
movq (%rax), %rcx
addq $0x1, %rcx
leaq 0x7f029(%rip), %rax     # 0xda7e0
movq %rcx, (%rax)
movzwl 0x15e(%rsp), %eax
movl %eax, %ecx
leaq 0x7f025(%rip), %rax     # 0xda7f0
movq (%rax,%rcx,8), %rdx
addq $0x1, %rdx
leaq 0x7f016(%rip), %rax     # 0xda7f0
movq %rdx, (%rax,%rcx,8)
movq 0x118(%rsp), %rdi
callq 0x58f60
movq 0x118(%rsp), %rax
movq %rax, 0x78(%rsp)
cmpq $0x0, %rax
je 0x5b808
movq 0x78(%rsp), %rdi
callq 0x8410
jmp 0x5b830
movq 0x88(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
callq 0x8410
jmp 0x5bc86
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x1d8, %rdi            # imm = 0x1D8
leaq 0x158(%rsp), %rsi
callq 0x5a300
movq %rax, %rcx
movq 0xb0(%rsp), %rax
movq %rcx, 0x100(%rsp)
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x1d8, %rdi            # imm = 0x1D8
callq 0x5a340
movq %rax, 0xf8(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x5a2e0
testb $0x1, %al
jne 0x5b8b7
jmp 0x5bc7e
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x1d8, %rdi            # imm = 0x1D8
leaq 0x158(%rsp), %rsi
callq 0x5d810
movq 0xb0(%rsp), %rdi
movl $0x0, 0xf4(%rsp)
movq $0x0, 0xe8(%rsp)
movl 0x158(%rsp), %esi
callq 0x5a3d0
movq 0xb0(%rsp), %rdi
movq %rax, 0xe0(%rsp)
movl 0x158(%rsp), %esi
callq 0x5a3f0
movq %rax, 0xd8(%rsp)
movq 0xe0(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rax
cmpq 0xd8(%rsp), %rax
ja 0x5baa7
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movw 0x15e(%rsp), %ax
movq 0xd0(%rsp), %rdx
movzwl %ax, %esi
callq 0x59760
testb $0x1, %al
jne 0x5b99b
jmp 0x5ba8c
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movw 0x15e(%rsp), %ax
movq 0xd0(%rsp), %rdx
movzwl %ax, %esi
callq 0x4ac90
testb $0x1, %al
jne 0x5b9d8
jmp 0x5ba11
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movw 0x15e(%rsp), %ax
movq 0xd0(%rsp), %rdx
movzwl %ax, %esi
callq 0x4ad70
jmp 0x5ba8a
movq 0xb0(%rsp), %rax
movq 0xd0(%rsp), %rcx
subq 0xe0(%rsp), %rcx
movl 0xb4(%rax), %eax
imulq %rax, %rcx
shrq $0x9, %rcx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, 0xc8(%rsp)
movq 0xe8(%rsp), %rax
andq 0xc8(%rsp), %rax
cmpq $0x0, %rax
jne 0x5ba88
movq 0xc8(%rsp), %rax
orq 0xe8(%rsp), %rax
movq %rax, 0xe8(%rsp)
movl 0xf4(%rsp), %eax
addl $0x200, %eax            # imm = 0x200
movl %eax, 0xf4(%rsp)
jmp 0x5ba8a
jmp 0x5ba8c
jmp 0x5ba8e
movq 0xd0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xd0(%rsp)
jmp 0x5b945
movq 0xb0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x15e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq (%rax), %rax
movl 0x158(%rsp), %ecx
shlq $0x4, %rcx
movl (%rax,%rcx), %eax
movl %eax, 0xc4(%rsp)
movl $0xb0, %edi
callq 0x8450
movq %rax, %rcx
movq 0xb0(%rsp), %rax
movq %rcx, 0x40(%rsp)
movw 0x15e(%rsp), %cx
movw %cx, 0x4a(%rsp)
movl 0x7c(%rax), %eax
movl %eax, %ecx
shll $0x9, %ecx
movl %ecx, 0x4c(%rsp)
movl 0x158(%rsp), %ecx
movq %rcx, 0x50(%rsp)
movl 0xc4(%rsp), %edx
movq %rdx, 0x58(%rsp)
movq %rcx, 0x60(%rsp)
movb %al, %cl
movl $0x1, %eax
shlq %cl, %rax
decq %rax
movq %rax, 0x68(%rsp)
callq 0x46500
movq %rax, 0x70(%rsp)
jmp 0x5bb48
movq 0x70(%rsp), %rdi
callq 0x46c50
movq %rax, 0x38(%rsp)
jmp 0x5bb59
movq 0x58(%rsp), %r9
movq 0x50(%rsp), %r8
movl 0x4c(%rsp), %ecx
movq 0x40(%rsp), %rdi
movw 0x4a(%rsp), %ax
movq 0x60(%rsp), %rsi
movq 0x68(%rsp), %r10
movq 0x38(%rsp), %r11
movq %rsp, %rdx
movq %r11, 0x20(%rdx)
movq %r10, 0x18(%rdx)
movq %rsi, 0x8(%rdx)
movq $0x0, 0x10(%rdx)
movq $0x0, (%rdx)
movzwl %ax, %edx
movl $0x3, %esi
callq 0x96320
jmp 0x5bbad
movq 0x40(%rsp), %rax
movq %rax, 0xb8(%rsp)
leaq 0x7ec1f(%rip), %rax     # 0xda7e0
movq (%rax), %rcx
addq $0x1, %rcx
leaq 0x7ec11(%rip), %rax     # 0xda7e0
movq %rcx, (%rax)
leaq 0x7ec0f(%rip), %rax     # 0xda7e8
movq (%rax), %rcx
addq $0x1, %rcx
leaq 0x7ec01(%rip), %rax     # 0xda7e8
movq %rcx, (%rax)
movzwl 0x15e(%rsp), %eax
movl %eax, %ecx
leaq 0x7ebf5(%rip), %rax     # 0xda7f0
movq (%rax,%rcx,8), %rdx
addq $0x1, %rdx
leaq 0x7ebe6(%rip), %rax     # 0xda7f0
movq %rdx, (%rax,%rcx,8)
movzwl 0x15e(%rsp), %eax
movl %eax, %ecx
leaq 0x7f3d1(%rip), %rax     # 0xdaff0
movq (%rax,%rcx,8), %rdx
addq $0x1, %rdx
leaq 0x7f3c2(%rip), %rax     # 0xdaff0
movq %rdx, (%rax,%rcx,8)
movq 0xb8(%rsp), %rdi
callq 0x58f60
movq 0xb8(%rsp), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, %rax
je 0x5bc5c
movq 0x30(%rsp), %rdi
callq 0x8410
jmp 0x5bc7e
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
callq 0x8410
jmp 0x5bc86
addq $0x168, %rsp            # imm = 0x168
retq
movq 0x110(%rsp), %rdi
callq 0x8770
nopw %cs:(%rax,%rax)
nopl (%rax)