// File: 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 %rbx
subq $0x190, %rsp            # imm = 0x190
movw %si, %ax
movq %rdi, 0x188(%rsp)
movw %ax, 0x186(%rsp)
movq %rdx, 0x178(%rsp)
movq 0x188(%rsp), %rdi
movq %rdi, 0xd0(%rsp)
movq 0x178(%rsp), %rsi
movzwl 0x186(%rsp), %edx
callq 0x5a1d0
movq 0xd0(%rsp), %rdi
movl %eax, 0x174(%rsp)
movw 0x186(%rsp), %cx
movl 0x174(%rsp), %edx
movq (%rdi), %rax
movzwl %cx, %esi
callq *0xf0(%rax)
testb $0x1, %al
jne 0x554fb
jmp 0x5558e
movq 0xd0(%rsp), %rdi
movw 0x186(%rsp), %si
movl 0x174(%rsp), %edx
movq (%rdi), %rax
xorl %ecx, %ecx
movzwl %si, %esi
callq *0xe0(%rax)
movq 0xd0(%rsp), %rdi
movq 0xa8(%rdi), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
addq $0xb8, %rax
movq %rax, 0xc8(%rsp)
movq 0x178(%rsp), %rsi
movzwl 0x186(%rsp), %edx
callq 0x5a1d0
movq 0xc8(%rsp), %rdi
movl %eax, 0x170(%rsp)
leaq 0x170(%rsp), %rsi
callq 0x5a370
movq %rax, 0x160(%rsp)
movb %dl, 0x168(%rsp)
jmp 0x55c6f
movq 0xd0(%rsp), %rax
movq 0x30(%rax), %rax
movq 0x50(%rax), %rdi
callq 0x59940
movq 0xd0(%rsp), %rdi
movl $0x0, 0x15c(%rsp)
movq $0x0, 0x150(%rsp)
movl 0x174(%rsp), %esi
callq 0x5a3d0
movq 0xd0(%rsp), %rdi
movq %rax, 0x148(%rsp)
movl 0x174(%rsp), %esi
callq 0x5a3f0
movq %rax, 0x140(%rsp)
movq 0x148(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x138(%rsp), %rax
cmpq 0x140(%rsp), %rax
ja 0x557cf
movq 0xd0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movw 0x186(%rsp), %ax
movq 0x138(%rsp), %rdx
movzwl %ax, %esi
callq 0x59760
testb $0x1, %al
jne 0x55658
jmp 0x557b4
movq 0xd0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movw 0x186(%rsp), %ax
movq 0x138(%rsp), %rdx
movzwl %ax, %esi
callq 0x4ac90
testb $0x1, %al
jne 0x55698
jmp 0x55739
movq 0xd0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movw 0x186(%rsp), %ax
movq 0x138(%rsp), %rdx
movzwl %ax, %esi
callq 0x4ad70
movq 0xd0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rdi
movw 0x186(%rsp), %ax
movq 0x138(%rsp), %rdx
movzwl %ax, %esi
callq 0x4a3f0
movq %rax, %rcx
movq 0xd0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x186(%rsp), %edx
movq (%rax,%rdx,8), %rax
movq 0x20(%rax), %rax
imulq $0x18, 0x138(%rsp), %rdx
addq %rdx, %rax
movq %rcx, (%rax)
jmp 0x557b2
movq 0xd0(%rsp), %rax
movq 0x138(%rsp), %rcx
subq 0x148(%rsp), %rcx
movl 0xb4(%rax), %eax
imulq %rax, %rcx
shrq $0x9, %rcx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, 0x130(%rsp)
movq 0x150(%rsp), %rax
andq 0x130(%rsp), %rax
cmpq $0x0, %rax
jne 0x557b0
movq 0x130(%rsp), %rax
orq 0x150(%rsp), %rax
movq %rax, 0x150(%rsp)
movl 0x15c(%rsp), %eax
addl $0x200, %eax            # imm = 0x200
movl %eax, 0x15c(%rsp)
jmp 0x557b2
jmp 0x557b4
jmp 0x557b6
movq 0x138(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x138(%rsp)
jmp 0x55602
movq 0xd0(%rsp), %rax
movq $0x0, 0x128(%rsp)
movq 0xa8(%rax), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq (%rax), %rax
movl 0x174(%rsp), %ecx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
movl %eax, 0x124(%rsp)
movl 0x124(%rsp), %eax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
cmpq %rcx, %rax
je 0x55a1b
movl $0xa0, %edi
callq 0x8450
movq %rax, 0x90(%rsp)
movw 0x186(%rsp), %ax
movw %ax, 0x9a(%rsp)
movl 0x15c(%rsp), %eax
movl %eax, 0x9c(%rsp)
movl 0x174(%rsp), %eax
movq %rax, 0xa0(%rsp)
movl 0x124(%rsp), %ecx
movq %rcx, 0xa8(%rsp)
movq %rax, 0xb0(%rsp)
movq 0x150(%rsp), %rax
movq %rax, 0xb8(%rsp)
callq 0x46500
movq %rax, 0xc0(%rsp)
jmp 0x5589a
movq 0xc0(%rsp), %rdi
callq 0x46c50
movq %rax, 0x88(%rsp)
jmp 0x558b1
movq 0xa8(%rsp), %r9
movq 0xa0(%rsp), %r8
movl 0x9c(%rsp), %ecx
movq 0x90(%rsp), %rdi
movw 0x9a(%rsp), %ax
movq 0xb0(%rsp), %rsi
movq 0xb8(%rsp), %r10
movq 0x88(%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 0x95f20
jmp 0x5591d
movq 0xd0(%rsp), %rdi
movq 0x90(%rsp), %rax
movq %rax, 0x128(%rsp)
movl 0x124(%rsp), %eax
movl %eax, %esi
movq 0x128(%rsp), %rdx
addq $0x38, %rdx
movq (%rdi), %rax
callq *0x88(%rax)
movq 0xd0(%rsp), %rax
movq 0x40(%rax), %rdi
movq 0x128(%rsp), %rsi
addq $0x38, %rsi
callq 0x7cd70
movq 0xd0(%rsp), %rax
movq 0xa8(%rax), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
addq $0x88, %rax
movq %rax, 0x80(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0x174(%rsp), %rsi
leaq 0x178(%rsp), %rdx
callq 0x5a2b0
movq 0x80(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0x5a280
movq %rax, %rcx
movq 0xd0(%rsp), %rax
movq %rcx, 0xf8(%rsp)
movq 0x30(%rax), %rax
movq 0x50(%rax), %rdi
movq 0x128(%rsp), %rsi
callq 0x59980
jmp 0x55a1b
movq 0x90(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
callq 0x8410
jmp 0x55c78
movl $0xb0, %edi
callq 0x8450
movq %rax, %rcx
movq 0xd0(%rsp), %rax
movq %rcx, 0x40(%rsp)
movw 0x186(%rsp), %cx
movw %cx, 0x4a(%rsp)
movl 0x7c(%rax), %eax
movl %eax, %ecx
shll $0x9, %ecx
movl %ecx, 0x4c(%rsp)
movl 0x174(%rsp), %ecx
movq %rcx, 0x50(%rsp)
movl 0x124(%rsp), %edx
movq %rdx, 0x58(%rsp)
movq %rcx, 0x60(%rsp)
movq 0x128(%rsp), %rcx
movq %rcx, 0x68(%rsp)
movb %al, %cl
movl $0x1, %eax
shlq %cl, %rax
decq %rax
movq %rax, 0x70(%rsp)
callq 0x46500
movq %rax, 0x78(%rsp)
jmp 0x55a96
movq 0x78(%rsp), %rdi
callq 0x46c50
movq %rax, 0x38(%rsp)
jmp 0x55aa7
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 0x70(%rsp), %r11
movq 0x38(%rsp), %rbx
movq %rsp, %rdx
movq %rbx, 0x20(%rdx)
movq %r11, 0x18(%rdx)
movq %r10, 0x10(%rdx)
movq %rsi, 0x8(%rdx)
movq $0x0, (%rdx)
movzwl %ax, %edx
movl $0x3, %esi
callq 0x96320
jmp 0x55afc
movq 0xd0(%rsp), %rdi
movq 0x40(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0xf0(%rsp), %rsi
callq 0x4cc40
movq 0xd0(%rsp), %rdi
movq 0xf0(%rsp), %rsi
movl 0x174(%rsp), %edx
xorl %ecx, %ecx
callq 0x4cc70
movq 0xd0(%rsp), %rdi
movq 0xa8(%rdi), %rax
movzwl 0x186(%rsp), %ecx
movq (%rax,%rcx,8), %rax
addq $0xb8, %rax
movq %rax, 0x30(%rsp)
movq 0x178(%rsp), %rsi
movzwl 0x186(%rsp), %edx
callq 0x5a1d0
movq 0x30(%rsp), %rdi
movl %eax, 0xec(%rsp)
leaq 0xec(%rsp), %rsi
callq 0x5a370
movq %rax, %rcx
movq 0xd0(%rsp), %rax
movq %rcx, 0xd8(%rsp)
movb %dl, 0xe0(%rsp)
movq 0x30(%rax), %rax
movq 0x50(%rax), %rdi
movq 0xf0(%rsp), %rsi
callq 0x59980
movq 0xd0(%rsp), %rax
leaq 0x84c12(%rip), %rcx     # 0xda7e0
movq (%rcx), %rdx
addq $0x1, %rdx
leaq 0x84c04(%rip), %rcx     # 0xda7e0
movq %rdx, (%rcx)
leaq 0x84c02(%rip), %rcx     # 0xda7e8
movq (%rcx), %rdx
addq $0x1, %rdx
leaq 0x84bf4(%rip), %rcx     # 0xda7e8
movq %rdx, (%rcx)
movzwl 0x186(%rsp), %ecx
movl %ecx, %edx
leaq 0x84be8(%rip), %rcx     # 0xda7f0
movq (%rcx,%rdx,8), %rsi
addq $0x1, %rsi
leaq 0x84bd9(%rip), %rcx     # 0xda7f0
movq %rsi, (%rcx,%rdx,8)
movzwl 0x186(%rsp), %ecx
movl %ecx, %edx
leaq 0x853c4(%rip), %rcx     # 0xdaff0
movq (%rcx,%rdx,8), %rsi
addq $0x1, %rsi
leaq 0x853b5(%rip), %rcx     # 0xdaff0
movq %rsi, (%rcx,%rdx,8)
movq 0x30(%rax), %rax
movq 0x50(%rax), %rdi
movq (%rdi), %rax
callq *0x30(%rax)
jmp 0x55c6f
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
callq 0x8410
jmp 0x55c78
addq $0x190, %rsp            # imm = 0x190
popq %rbx
retq
movq 0x118(%rsp), %rdi
callq 0x8770
nopw %cs:(%rax,%rax)