// File: /workspace/github_cpp_makefile_star2_O3/CMU-SAFARI[P]MQSim/src/ssd/Address_Mapping_Unit_Page_Level.cpp
// Function: SSD_Components::Address_Mapping_Unit_Page_Level::generate_flash_writeback_request_for_mapping_data(unsigned short, unsigned long)
void Address_Mapping_Unit_Page_Level::generate_flash_writeback_request_for_mapping_data(const stream_id_type stream_id, const LPA_type lpn)
	{
		MVPN_type mvpn = get_MVPN(lpn, stream_id);
		if (is_mvpn_locked_for_gc(stream_id, mvpn)) {
			manage_mapping_transaction_facing_barrier(stream_id, mvpn, false);
			domains[stream_id]->DepartingMappingEntries.insert(get_MVPN(lpn, stream_id));
		} else {
			ftl->TSU->Prepare_for_transaction_submit();

			//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 startLPN = get_start_LPN_in_MVP(mvpn);
			LPA_type endLPN = get_end_LPN_in_MVP(mvpn);
			for (LPA_type lpn_itr = startLPN; lpn_itr <= endLPN; 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);
						domains[stream_id]->GlobalMappingTable[lpn_itr].PPA = domains[stream_id]->CMT->Retrieve_ppa(stream_id, lpn_itr);
					} else {
						page_status_type bitlocation = (((page_status_type)0x1) << (((lpn_itr - startLPN) * 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
			NVM_Transaction_Flash_RD* readTR = NULL;
			MPPN_type mppn = domains[stream_id]->GlobalTranslationDirectory[mvpn].MPPN;
			if (mppn != NO_MPPN) {
				readTR = new NVM_Transaction_Flash_RD(Transaction_Source_Type::MAPPING, stream_id, read_size,
					mvpn, mppn, NULL, mvpn, NULL, readSectorsBitmap, CurrentTimeStamp);
				Convert_ppa_to_address(mppn, readTR->Address);
				block_manager->Read_transaction_issued(readTR->Address);//Inform block_manager as soon as the transaction's target address is determined
				domains[stream_id]->ArrivingMappingEntries.insert(std::pair<MVPN_type, LPA_type>(mvpn, lpn));
				ftl->TSU->Submit_transaction(readTR);
			}

			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, readTR, (((page_status_type)0x1) << sector_no_per_page) - 1, CurrentTimeStamp);
			allocate_plane_for_translation_write(writeTR);
			allocate_page_in_plane_for_translation_write(writeTR, mvpn, false);
			domains[stream_id]->DepartingMappingEntries.insert(get_MVPN(lpn, stream_id));
			ftl->TSU->Submit_transaction(writeTR);

			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]++;

			ftl->TSU->Schedule();
		}
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdx, %r15
movl %esi, %ebp
movq %rdi, %rbx
movl 0xc0(%rdi), %ecx
movq %rdx, %rax
xorl %edx, %edx
divq %rcx
movq %rax, %r12
movq (%rdi), %rax
movl %r12d, %edx
callq *0xf0(%rax)
testb %al, %al
je 0x2def2
movq (%rbx), %rax
movzwl %bp, %r14d
movq %rbx, %rdi
movl %r14d, %esi
movl %r12d, %edx
xorl %ecx, %ecx
callq *0xe0(%rax)
movq 0xa8(%rbx), %rax
movl $0xb8, %edi
addq (%rax,%r14,8), %rdi
movl 0xc0(%rbx), %ecx
movq %r15, %rax
xorl %edx, %edx
divq %rcx
leaq 0x20(%rsp), %rsi
movl %eax, (%rsi)
callq 0x312f2
jmp 0x2e281
movq 0x30(%rbx), %rax
movq 0x50(%rax), %rdi
callq 0x2f762
movl 0xc0(%rbx), %eax
leal 0x1(%r12), %r13d
imull %eax, %r13d
movl %eax, %r14d
movq %r12, 0x10(%rsp)
imull %r12d, %r14d
decl %r13d
movzwl %bp, %r12d
cmpl %r13d, %r14d
movq %r15, 0x18(%rsp)
jbe 0x2df35
xorl %r13d, %r13d
xorl %ebp, %ebp
jmp 0x2e064
movq %r12, %r15
shlq $0x38, %r15
xorl %ebp, %ebp
movq $0x0, 0x8(%rsp)
movq $0x0, (%rsp)
movq %r15, 0x30(%rsp)
movq 0xa8(%rbx), %rax
movq (%rax,%r12,8), %rax
movq 0x10(%rax), %rdi
movq %r14, %rax
orq %r15, %rax
movq %rax, 0x20(%rsp)
leaq 0x20(%rsp), %rsi
callq 0x30a0c
testq %rax, %rax
je 0x2e048
movq 0x10(%rax), %rax
cmpl $0x2, 0x14(%rax)
jne 0x2e048
movq 0xa8(%rbx), %rax
movq (%rax,%r12,8), %rax
movq 0x10(%rax), %rdi
movl %r12d, %esi
movq %r14, %rdx
callq 0x297c8
testb %al, %al
je 0x2e007
movq 0xa8(%rbx), %rax
leal (,%r12,8), %r15d
movq (%rax,%r15), %rax
movq 0x10(%rax), %rdi
movl %r12d, %esi
movq %r14, %rdx
callq 0x2983a
movq 0xa8(%rbx), %rax
movq (%rax,%r15), %rax
movq 0x10(%rax), %rdi
movl %r12d, %esi
movq %r14, %rdx
callq 0x293bc
movq 0xa8(%rbx), %rcx
movq (%rcx,%r15), %rcx
movq 0x30(%rsp), %r15
movq 0x20(%rcx), %rcx
leaq (%r14,%r14,2), %rdx
movq %rax, (%rcx,%rdx,8)
jmp 0x2e048
movl 0xb4(%rbx), %ecx
imull %ebp, %ecx
shrl $0x9, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq 0x8(%rsp), %rdi
leal 0x200(%rdi), %edx
movq (%rsp), %rsi
btq %rcx, %rsi
movl $0x0, %ecx
cmovbq %rcx, %rax
cmovbl %edi, %edx
orq %rax, %rsi
movq %rsi, (%rsp)
movl %edx, %eax
movq %rax, 0x8(%rsp)
leaq 0x1(%r14), %rax
incq %rbp
cmpq %r13, %r14
movq %rax, %r14
jb 0x2df54
movq (%rsp), %r13
movq 0x8(%rsp), %rbp
movq 0xa8(%rbx), %rax
movq (%rax,%r12,8), %rax
movq (%rax), %rax
movl 0x10(%rsp), %r14d
movq %r14, %rcx
shlq $0x4, %rcx
movl (%rax,%rcx), %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rcx, (%rsp)
cmpq %rax, %rcx
je 0x2e166
movl $0xa0, %edi
callq 0x73a0
movq %rax, %r15
callq 0x28018
movq %rax, %rdi
callq 0x2841a
subq $0x8, %rsp
xorl %r10d, %r10d
movq %r15, %rdi
movl $0x3, %esi
movl %r12d, %edx
movl %ebp, %ecx
movq %r14, %r8
movq 0x8(%rsp), %r9
pushq %rax
pushq %r13
pushq %r10
pushq %r14
pushq %r10
callq 0x4802c
addq $0x30, %rsp
movq %r15, %rbp
addq $0x38, %rbp
movq (%rbx), %rax
movq %rbx, %rdi
movq (%rsp), %rsi
movq %rbp, %rdx
callq *0x88(%rax)
movq 0x40(%rbx), %rdi
movq %rbp, %rsi
callq 0x3d7d8
movq 0xa8(%rbx), %rax
movl $0x88, %edi
addq (%rax,%r12,8), %rdi
leaq 0x20(%rsp), %rsi
movq 0x10(%rsp), %rax
movl %eax, (%rsi)
movq 0x18(%rsp), %rax
movq %rax, 0x8(%rsi)
callq 0x31222
movq 0x30(%rbx), %rax
movq %r12, %r13
movq 0x50(%rax), %r12
leaq 0x78(%r12), %rbp
movl $0x18, %edi
callq 0x73a0
movq %r15, 0x10(%rax)
movq %rax, %rdi
movq %rbp, %rsi
callq 0x7060
incq 0x88(%r12)
movq %r13, %r12
movq %r15, 0x8(%rsp)
jmp 0x2e16f
movq $0x0, 0x8(%rsp)
movl $0xb0, %edi
callq 0x73a0
movq %rax, %r15
movl 0x7c(%rbx), %ebp
movq $-0x1, %r13
movl %ebp, %ecx
shlq %cl, %r13
callq 0x28018
movq %rax, %rdi
callq 0x2841a
shll $0x9, %ebp
notq %r13
subq $0x8, %rsp
movq %r15, %rdi
movl $0x3, %esi
movl %r12d, %edx
movl %ebp, %ecx
movq %r14, %r8
movq 0x8(%rsp), %r9
pushq %rax
pushq %r13
pushq 0x20(%rsp)
pushq %r14
pushq $0x0
callq 0x481c8
addq $0x30, %rsp
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2b3c6
movq %rbx, %rdi
movq %r15, %rsi
movq 0x10(%rsp), %rdx
xorl %ecx, %ecx
callq 0x2a856
movq 0xa8(%rbx), %rax
shll $0x3, %r12d
movl $0xb8, %edi
addq (%rax,%r12), %rdi
movl 0xc0(%rbx), %ecx
movq 0x18(%rsp), %rax
xorl %edx, %edx
divq %rcx
leaq 0x20(%rsp), %rsi
movl %eax, (%rsi)
callq 0x312f2
movq 0x30(%rbx), %rax
movq %r12, %r13
movq 0x50(%rax), %r12
leaq 0x78(%r12), %r14
movl $0x18, %edi
callq 0x73a0
movq %r15, 0x10(%rax)
movq %rax, %rdi
movq %r14, %rsi
callq 0x7060
incq 0x88(%r12)
leaq 0x414d0(%rip), %rax     # 0x6f720
incq (%rax)
leaq 0x414ce(%rip), %rax     # 0x6f728
incq (%rax)
leaq 0x414cc(%rip), %rax     # 0x6f730
incq (%rax,%r13)
leaq 0x41cc1(%rip), %rax     # 0x6ff30
incq (%rax,%r13)
movq 0x30(%rbx), %rax
movq 0x50(%rax), %rdi
movq (%rdi), %rax
callq *0x30(%rax)
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2e292
movq %rax, %rbx
movq %r15, %rdi
callq 0x7370
movq %rbx, %rdi
callq 0x7620
nop