// File: /workspace/github_cpp_makefile_star2_O2/CMU-SAFARI[P]MQSim/src/ssd/Address_Mapping_Unit_Page_Level.cpp
// Function: SSD_Components::Address_Mapping_Unit_Page_Level::allocate_page_in_plane_for_user_write(SSD_Components::NVM_Transaction_Flash_WR*, bool)
void Address_Mapping_Unit_Page_Level::allocate_page_in_plane_for_user_write(NVM_Transaction_Flash_WR* transaction, bool is_for_gc)
	{
		AddressMappingDomain* domain = domains[transaction->Stream_id];
		PPA_type old_ppa = domain->Get_ppa(ideal_mapping_table, transaction->Stream_id, transaction->LPA);

		if (old_ppa == NO_PPA)  /*this is the first access to the logical page*/
		{
			if (is_for_gc) {
				PRINT_ERROR("Unexpected mapping table status in allocate_page_in_plane_for_user_write function for a GC/WL write!")
			}
		} else {
			if (is_for_gc) {
				NVM::FlashMemory::Physical_Page_Address addr;
				Convert_ppa_to_address(old_ppa, addr);
				block_manager->Invalidate_page_in_block(transaction->Stream_id, addr);
				page_status_type page_status_in_cmt = domain->Get_page_status(ideal_mapping_table, transaction->Stream_id, transaction->LPA);
				if (page_status_in_cmt != transaction->write_sectors_bitmap)
					PRINT_ERROR("Unexpected mapping table status in allocate_page_in_plane_for_user_write for a GC/WL write!")
			} else {
				page_status_type prev_page_status = domain->Get_page_status(ideal_mapping_table, transaction->Stream_id, transaction->LPA);
				page_status_type status_intersection = transaction->write_sectors_bitmap & prev_page_status;
				//check if an update read is required
				if (status_intersection == prev_page_status) {
					NVM::FlashMemory::Physical_Page_Address addr;
					Convert_ppa_to_address(old_ppa, addr);
					block_manager->Invalidate_page_in_block(transaction->Stream_id, addr);
				} else {
					page_status_type read_pages_bitmap = status_intersection ^ prev_page_status;
					NVM_Transaction_Flash_RD *update_read_tr = new NVM_Transaction_Flash_RD(transaction->Source, transaction->Stream_id,
						count_sector_no_from_status_bitmap(read_pages_bitmap) * SECTOR_SIZE_IN_BYTE, transaction->LPA, old_ppa, transaction->UserIORequest,
						transaction->Content, transaction, read_pages_bitmap, domain->GlobalMappingTable[transaction->LPA].TimeStamp);
					Convert_ppa_to_address(old_ppa, update_read_tr->Address);
					block_manager->Read_transaction_issued(update_read_tr->Address);//Inform block manager about a new transaction as soon as the transaction's target address is determined
					block_manager->Invalidate_page_in_block(transaction->Stream_id, update_read_tr->Address);
					transaction->RelatedRead = update_read_tr;
				}
			}
		}

		/*The following lines should not be ordered with respect to the block_manager->Invalidate_page_in_block
		* function call in the above code blocks. Otherwise, GC may be invoked (due to the call to Allocate_block_....) and
		* may decide to move a page that is just invalidated.*/
		if (is_for_gc) {
			block_manager->Allocate_block_and_page_in_plane_for_gc_write(transaction->Stream_id, transaction->Address);
		} else {
			block_manager->Allocate_block_and_page_in_plane_for_user_write(transaction->Stream_id, transaction->Address);
		}
		transaction->PPA = Convert_address_to_ppa(transaction->Address);
		domain->Update_mapping_info(ideal_mapping_table, transaction->Stream_id, transaction->LPA, transaction->PPA,
			((NVM_Transaction_Flash_WR*)transaction)->write_sectors_bitmap | domain->Get_page_status(ideal_mapping_table, transaction->Stream_id, transaction->LPA));
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %r15
movq 0xa8(%rdi), %rax
movzwl (%rsi), %edx
movq (%rax,%rdx,8), %rbx
movzbl 0x4c(%rdi), %esi
movq 0x58(%r14), %rcx
movq %rbx, %rdi
callq 0x26518
cmpq $-0x1, %rax
je 0x23372
movq %rax, %r12
testb %bpl, %bpl
je 0x2339d
xorps %xmm0, %xmm0
leaq 0x10(%rsp), %r13
movaps %xmm0, (%r13)
andq $0x0, 0x10(%r13)
movq (%r15), %rax
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *0x88(%rax)
movq 0x40(%r15), %rdi
movzwl (%r14), %esi
movq (%rdi), %rax
movq %r13, %rdx
callq *0x30(%rax)
movzbl 0x4c(%r15), %esi
movzwl (%r14), %edx
movq 0x58(%r14), %rcx
movq %rbx, %rdi
callq 0x265fc
cmpq 0x98(%r14), %rax
jne 0x23522
pushq $0x18
jmp 0x234aa
testb %bpl, %bpl
je 0x234a8
movq 0x3ec6e(%rip), %rbx     # 0x61ff0
leaq 0x211ff(%rip), %rsi     # 0x44588
movq %rbx, %rdi
callq 0x7360
leaq 0x235d2(%rip), %rsi     # 0x4696a
jmp 0x2353f
movzbl 0x4c(%r15), %esi
movzwl (%r14), %edx
movq 0x58(%r14), %rcx
movq %rbx, %rdi
callq 0x265fc
movq 0x98(%r14), %rbp
andq %rax, %rbp
cmpq %rax, %rbp
jne 0x233fb
xorps %xmm0, %xmm0
leaq 0x10(%rsp), %r13
movaps %xmm0, (%r13)
andq $0x0, 0x10(%r13)
movq (%r15), %rax
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *0x88(%rax)
movq 0x40(%r15), %rdi
movzwl (%r14), %esi
movq (%rdi), %rax
movq %r13, %rdx
callq *0x30(%rax)
jmp 0x234a8
xorq %rax, %rbp
movl $0xa0, %edi
callq 0x7370
movq %rax, %r13
movl 0x4(%r14), %eax
movl %eax, 0x4(%rsp)
movzwl (%r14), %eax
movl %eax, (%rsp)
movq %rbp, %rdi
callq 0x2661d
shll $0x9, %eax
movq 0x58(%r14), %r8
movq 0x20(%rbx), %r10
imulq $0x18, %r8, %r11
subq $0x8, %rsp
movq %r13, 0x10(%rsp)
movq %r13, %rdi
movl 0xc(%rsp), %esi
movl 0x8(%rsp), %edx
movl %eax, %ecx
movq %r12, %r9
pushq 0x10(%r10,%r11)
pushq %rbp
pushq %r14
pushq 0x80(%r14)
pushq 0x10(%r14)
callq 0x3a134
addq $0x30, %rsp
movq 0x8(%rsp), %rbp
movq %rbp, %r13
addq $0x38, %r13
movq (%r15), %rax
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *0x88(%rax)
movq 0x40(%r15), %rdi
movq %r13, %rsi
callq 0x31b8a
movq 0x40(%r15), %rdi
movzwl (%r14), %esi
movq (%rdi), %rax
movq %r13, %rdx
callq *0x30(%rax)
movq %rbp, 0x88(%r14)
pushq $0x10
popq %rax
movq 0x40(%r15), %rdi
movzwl (%r14), %esi
leaq 0x38(%r14), %r12
movq (%rdi), %rcx
movq %r12, %rdx
callq *(%rcx,%rax)
movq (%r15), %rax
movq %r15, %rdi
movq %r12, %rsi
callq *0x90(%rax)
movq %rax, %r12
movq %rax, 0x60(%r14)
movzbl 0x4c(%r15), %ebp
movzwl (%r14), %r15d
movq 0x58(%r14), %r13
movq 0x98(%r14), %r14
movq %rbx, %rdi
movl %ebp, %esi
movl %r15d, %edx
movq %r13, %rcx
callq 0x265fc
orq %rax, %r14
movq %rbx, %rdi
movl %ebp, %esi
movl %r15d, %edx
movq %r13, %rcx
movq %r12, %r8
movq %r14, %r9
callq 0x265a6
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x3eac7(%rip), %rbx     # 0x61ff0
leaq 0x21058(%rip), %rsi     # 0x44588
movq %rbx, %rdi
callq 0x7360
leaq 0x23490(%rip), %rsi     # 0x469cf
movq %rbx, %rdi
callq 0x7360
movq %rax, %rdi
callq 0x71a0
movq 0x3ea7a(%rip), %rdi     # 0x61fd0
callq 0x73d0
pushq $0x1
popq %rdi
callq 0x73e0
movq %rax, %rbx
movq 0x8(%rsp), %rdi
callq 0x7340
movq %rbx, %rdi
callq 0x75d0