// File: CMU-SAFARI[P]MQSim/src/ssd/Flash_Block_Manager.cpp
// Function: SSD_Components::Flash_Block_Manager::Allocate_Pages_in_block_and_invalidate_remaining_for_preconditioning(unsigned short, NVM::FlashMemory::Physical_Page_Address const&, std::vector<NVM::FlashMemory::Physical_Page_Address, std::allocator<NVM::FlashMemory::Physical_Page_Address>>&)
void Flash_Block_Manager::Allocate_Pages_in_block_and_invalidate_remaining_for_preconditioning(const stream_id_type stream_id, const NVM::FlashMemory::Physical_Page_Address& plane_address, std::vector<NVM::FlashMemory::Physical_Page_Address>& page_addresses)
	{
		if(page_addresses.size() > pages_no_per_block) {
			PRINT_ERROR("Error while precondition a physical block: the size of the address list is larger than the pages_no_per_block!")
		}
			
		PlaneBookKeepingType *plane_record = &plane_manager[plane_address.ChannelID][plane_address.ChipID][plane_address.DieID][plane_address.PlaneID];
		if (plane_record->Data_wf[stream_id]->Current_page_write_index > 0) {
			PRINT_ERROR("Illegal operation: the Allocate_Pages_in_block_and_invalidate_remaining_for_preconditioning function should be executed for an erased block!")
		}

		//Assign physical addresses
		for (int i = 0; i < page_addresses.size(); i++) {
			plane_record->Valid_pages_count++;
			plane_record->Free_pages_count--;
			page_addresses[i].BlockID = plane_record->Data_wf[stream_id]->BlockID;
			page_addresses[i].PageID = plane_record->Data_wf[stream_id]->Current_page_write_index++;
			plane_record->Check_bookkeeping_correctness(page_addresses[i]);
		}

		//Invalidate the remaining pages in the block
		NVM::FlashMemory::Physical_Page_Address target_address(plane_address);
		while (plane_record->Data_wf[stream_id]->Current_page_write_index < pages_no_per_block) {
			plane_record->Free_pages_count--;
			target_address.BlockID = plane_record->Data_wf[stream_id]->BlockID;
			target_address.PageID = plane_record->Data_wf[stream_id]->Current_page_write_index++;
			Invalidate_page_in_block_for_preconditioning(stream_id, target_address);
			plane_record->Check_bookkeeping_correctness(plane_address);
		}

		//Update the write frontier
		plane_record->Data_wf[stream_id] = plane_record->Get_a_free_block(stream_id, false);
	}

// Assembly:
subq $0x68, %rsp
movw %si, %ax
movq %rdi, 0x60(%rsp)
movw %ax, 0x5e(%rsp)
movq %rdx, 0x50(%rsp)
movq %rcx, 0x48(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x48(%rsp), %rdi
callq 0x45780
movq 0x18(%rsp), %rcx
movl 0x34(%rcx), %ecx
cmpq %rcx, %rax
jbe 0x7ab77
movq 0x5f4bd(%rip), %rdi     # 0xd9ff0
leaq 0x2fdae(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x5f4aa(%rip), %rdi     # 0xd9ff0
leaq 0x32e9b(%rip), %rsi     # 0xad9e8
callq 0x8440
movq %rax, %rdi
movq 0x5f3fc(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x5f468(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movq 0x18(%rsp), %rax
movq 0x8(%rax), %rax
movq 0x50(%rsp), %rcx
movl (%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x50(%rsp), %rcx
movl 0x4(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x50(%rsp), %rcx
movl 0x8(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x50(%rsp), %rcx
movl 0xc(%rcx), %ecx
imulq $0xe0, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movzwl 0x5e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
cmpl $0x0, 0x4(%rax)
jbe 0x7ac1d
movq 0x5f417(%rip), %rdi     # 0xd9ff0
leaq 0x2fd08(%rip), %rsi     # 0xaa8e8
callq 0x8440
movq 0x5f404(%rip), %rdi     # 0xd9ff0
leaq 0x32e64(%rip), %rsi     # 0xada57
callq 0x8440
movq %rax, %rdi
movq 0x5f356(%rip), %rsi     # 0xd9f58
callq 0x8480
movq 0x5f3c2(%rip), %rdi     # 0xd9fd0
callq 0x84f0
movl $0x1, %edi
callq 0x8500
movl $0x0, 0x3c(%rsp)
movslq 0x3c(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x48(%rsp), %rdi
callq 0x45780
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jae 0x7acfd
movq 0x40(%rsp), %rax
movl 0x8(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8(%rax)
movq 0x40(%rsp), %rax
movl 0x4(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x4(%rax)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movzwl 0x5e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movl (%rax), %eax
movl %eax, (%rsp)
movq 0x48(%rsp), %rdi
movslq 0x3c(%rsp), %rsi
callq 0x45760
movl (%rsp), %ecx
movl %ecx, 0x10(%rax)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movzwl 0x5e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movl 0x4(%rax), %ecx
movl %ecx, 0x4(%rsp)
addl $0x1, %ecx
movl %ecx, 0x4(%rax)
movq 0x48(%rsp), %rdi
movslq 0x3c(%rsp), %rsi
callq 0x45760
movl 0x4(%rsp), %ecx
movl %ecx, 0x14(%rax)
movq 0x40(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x48(%rsp), %rdi
movslq 0x3c(%rsp), %rsi
callq 0x45760
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x7c7c0
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x7ac25
movq 0x50(%rsp), %rsi
leaq 0x24(%rsp), %rdi
callq 0x5e380
movq 0x18(%rsp), %rcx
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movzwl 0x5e(%rsp), %edx
movq (%rax,%rdx,8), %rax
movl 0x4(%rax), %eax
cmpl 0x34(%rcx), %eax
jae 0x7ad9e
movq 0x18(%rsp), %rdi
movq 0x40(%rsp), %rax
movl 0x4(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x4(%rax)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movzwl 0x5e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movl (%rax), %eax
movl %eax, 0x34(%rsp)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movzwl 0x5e(%rsp), %ecx
movq (%rax,%rcx,8), %rcx
movl 0x4(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x4(%rcx)
movl %eax, 0x38(%rsp)
movw 0x5e(%rsp), %cx
movq (%rdi), %rax
leaq 0x24(%rsp), %rdx
movzwl %cx, %esi
callq *0x38(%rax)
movq 0x40(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x7c7c0
jmp 0x7ad0c
movq 0x40(%rsp), %rdi
xorl %edx, %edx
movzwl 0x5e(%rsp), %esi
callq 0x7c270
movq %rax, %rdx
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movzwl 0x5e(%rsp), %ecx
movq %rdx, (%rax,%rcx,8)
addq $0x68, %rsp
retq
nopl (%rax)