// File: CMU-SAFARI[P]MQSim/src/ssd/Address_Mapping_Unit_Page_Level.cpp
// Function: SSD_Components::Address_Mapping_Unit_Page_Level::query_cmt(SSD_Components::NVM_Transaction_Flash*)
bool Address_Mapping_Unit_Page_Level::query_cmt(NVM_Transaction_Flash* transaction)
	{
		stream_id_type stream_id = transaction->Stream_id;
		Stats::total_CMT_queries++;
		Stats::total_CMT_queries_per_stream[stream_id]++;

		if (domains[stream_id]->Mapping_entry_accessible(ideal_mapping_table, stream_id, transaction->LPA))//Either limited or unlimited CMT
		{
			Stats::CMT_hits_per_stream[stream_id]++;
			Stats::CMT_hits++;
			if (transaction->Type == Transaction_Type::READ) {
				Stats::total_readTR_CMT_queries_per_stream[stream_id]++;
				Stats::total_readTR_CMT_queries++;
				Stats::readTR_CMT_hits_per_stream[stream_id]++;
				Stats::readTR_CMT_hits++;
			} else {
				//This is a write transaction
				Stats::total_writeTR_CMT_queries++;
				Stats::total_writeTR_CMT_queries_per_stream[stream_id]++;
				Stats::writeTR_CMT_hits++;
				Stats::writeTR_CMT_hits_per_stream[stream_id]++;
			}

			if (translate_lpa_to_ppa(stream_id, transaction)) {
				return true;
			} else {
				mange_unsuccessful_translation(transaction);
				return false;
			}
		} else {//Limited CMT
			//Maybe we can catch mapping data from an on-the-fly write back request
			if (request_mapping_entry(stream_id, transaction->LPA)) {
				Stats::CMT_miss++;
				Stats::CMT_miss_per_stream[stream_id]++;
				if (transaction->Type == Transaction_Type::READ) {
					Stats::total_readTR_CMT_queries++;
					Stats::total_readTR_CMT_queries_per_stream[stream_id]++;
					Stats::readTR_CMT_miss++;
					Stats::readTR_CMT_miss_per_stream[stream_id]++;
				} else { //This is a write transaction
					Stats::total_writeTR_CMT_queries++;
					Stats::total_writeTR_CMT_queries_per_stream[stream_id]++;
					Stats::writeTR_CMT_miss++;
					Stats::writeTR_CMT_miss_per_stream[stream_id]++;
				}
				if (translate_lpa_to_ppa(stream_id, transaction)) {
					return true;
				} else {
					mange_unsuccessful_translation(transaction);
					return false;
				}
			} else {
				if (transaction->Type == Transaction_Type::READ) {
					Stats::total_readTR_CMT_queries++;
					Stats::total_readTR_CMT_queries_per_stream[stream_id]++;
					Stats::readTR_CMT_miss++;
					Stats::readTR_CMT_miss_per_stream[stream_id]++;
					domains[stream_id]->Waiting_unmapped_read_transactions.insert(std::pair<LPA_type, NVM_Transaction_Flash*>(transaction->LPA, transaction));
				} else {//This is a write transaction
					Stats::total_writeTR_CMT_queries++;
					Stats::total_writeTR_CMT_queries_per_stream[stream_id]++;
					Stats::writeTR_CMT_miss++;
					Stats::writeTR_CMT_miss_per_stream[stream_id]++;
					domains[stream_id]->Waiting_unmapped_program_transactions.insert(std::pair<LPA_type, NVM_Transaction_Flash*>(transaction->LPA, transaction));
				}
			}

			return false;
		}
	}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x58(%rsp)
movq %rsi, 0x50(%rsp)
movq 0x58(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x50(%rsp), %rcx
movw (%rcx), %cx
movw %cx, 0x4e(%rsp)
leaq 0x8e4b4(%rip), %rcx     # 0xdb810
movl (%rcx), %edx
addl $0x1, %edx
leaq 0x8e4a8(%rip), %rcx     # 0xdb810
movl %edx, (%rcx)
movzwl 0x4e(%rsp), %ecx
movl %ecx, %edx
leaq 0x90cd8(%rip), %rcx     # 0xde050
movl (%rcx,%rdx,4), %esi
addl $0x1, %esi
leaq 0x90ccb(%rip), %rcx     # 0xde050
movl %esi, (%rcx,%rdx,4)
movq 0xa8(%rax), %rcx
movzwl 0x4e(%rsp), %edx
movq (%rcx,%rdx,8), %rdi
movb 0x4c(%rax), %dl
movw 0x4e(%rsp), %ax
movq 0x50(%rsp), %rcx
movq 0x58(%rcx), %rcx
andb $0x1, %dl
movzbl %dl, %esi
movzwl %ax, %edx
callq 0x599b0
testb $0x1, %al
jne 0x4d3c0
jmp 0x4d50c
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x8f482(%rip), %rax     # 0xdc850
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x8f475(%rip), %rax     # 0xdc850
movl %edx, (%rax,%rcx,4)
leaq 0x8e413(%rip), %rax     # 0xdb7f8
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e407(%rip), %rax     # 0xdb7f8
movl %ecx, (%rax)
movq 0x50(%rsp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x4d466
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x91044(%rip), %rax     # 0xde450
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x91037(%rip), %rax     # 0xde450
movl %edx, (%rax,%rcx,4)
leaq 0x8e3f1(%rip), %rax     # 0xdb814
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e3e5(%rip), %rax     # 0xdb814
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x8f811(%rip), %rax     # 0xdcc50
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x8f804(%rip), %rax     # 0xdcc50
movl %edx, (%rax,%rcx,4)
leaq 0x8e3a6(%rip), %rax     # 0xdb7fc
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e39a(%rip), %rax     # 0xdb7fc
movl %ecx, (%rax)
jmp 0x4d4cc
leaq 0x8e3ab(%rip), %rax     # 0xdb818
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e39f(%rip), %rax     # 0xdb818
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x913c7(%rip), %rax     # 0xde850
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x913ba(%rip), %rax     # 0xde850
movl %edx, (%rax,%rcx,4)
leaq 0x8e360(%rip), %rax     # 0xdb800
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e354(%rip), %rax     # 0xdb800
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x8fb94(%rip), %rax     # 0xdd050
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x8fb87(%rip), %rax     # 0xdd050
movl %edx, (%rax,%rcx,4)
movq 0x10(%rsp), %rdi
movw 0x4e(%rsp), %ax
movq 0x50(%rsp), %rdx
movzwl %ax, %esi
callq 0x4d800
testb $0x1, %al
jne 0x4d4e9
jmp 0x4d4f3
movb $0x1, 0x67(%rsp)
jmp 0x4d7f5
movq 0x10(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x4d960
movb $0x0, 0x67(%rsp)
jmp 0x4d7f5
movq 0x10(%rsp), %rdi
movw 0x4e(%rsp), %ax
movq 0x50(%rsp), %rcx
movq 0x58(%rcx), %rdx
movzwl %ax, %esi
callq 0x4d9d0
testb $0x1, %al
jne 0x4d530
jmp 0x4d67c
leaq 0x8e2cd(%rip), %rax     # 0xdb804
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e2c1(%rip), %rax     # 0xdb804
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x8fefd(%rip), %rax     # 0xdd450
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x8fef0(%rip), %rax     # 0xdd450
movl %edx, (%rax,%rcx,4)
movq 0x50(%rsp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x4d5d6
leaq 0x8e29f(%rip), %rax     # 0xdb814
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e293(%rip), %rax     # 0xdb814
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x90ebf(%rip), %rax     # 0xde450
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x90eb2(%rip), %rax     # 0xde450
movl %edx, (%rax,%rcx,4)
leaq 0x8e260(%rip), %rax     # 0xdb808
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e254(%rip), %rax     # 0xdb808
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x9028c(%rip), %rax     # 0xdd850
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x9027f(%rip), %rax     # 0xdd850
movl %edx, (%rax,%rcx,4)
jmp 0x4d63c
leaq 0x8e23b(%rip), %rax     # 0xdb818
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e22f(%rip), %rax     # 0xdb818
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x91257(%rip), %rax     # 0xde850
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x9124a(%rip), %rax     # 0xde850
movl %edx, (%rax,%rcx,4)
leaq 0x8e1fc(%rip), %rax     # 0xdb80c
movl (%rax), %ecx
addl $0x1, %ecx
leaq 0x8e1f0(%rip), %rax     # 0xdb80c
movl %ecx, (%rax)
movzwl 0x4e(%rsp), %eax
movl %eax, %ecx
leaq 0x90624(%rip), %rax     # 0xddc50
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
leaq 0x90617(%rip), %rax     # 0xddc50
movl %edx, (%rax,%rcx,4)
movq 0x10(%rsp), %rdi
movw 0x4e(%rsp), %ax
movq 0x50(%rsp), %rdx
movzwl %ax, %esi
callq 0x4d800
testb $0x1, %al
jne 0x4d659
jmp 0x4d663
movb $0x1, 0x67(%rsp)
jmp 0x4d7f5
movq 0x10(%rsp), %rdi
movq 0x50(%rsp), %rsi
callq 0x4d960
movb $0x0, 0x67(%rsp)
jmp 0x4d7f5
movq 0x50(%rsp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x4d740
movq 0x10(%rsp), %rax
leaq 0x8e17d(%rip), %rcx     # 0xdb814
movl (%rcx), %edx
addl $0x1, %edx
leaq 0x8e171(%rip), %rcx     # 0xdb814
movl %edx, (%rcx)
movzwl 0x4e(%rsp), %ecx
movl %ecx, %edx
leaq 0x90d9d(%rip), %rcx     # 0xde450
movl (%rcx,%rdx,4), %esi
addl $0x1, %esi
leaq 0x90d90(%rip), %rcx     # 0xde450
movl %esi, (%rcx,%rdx,4)
leaq 0x8e13e(%rip), %rcx     # 0xdb808
movl (%rcx), %edx
addl $0x1, %edx
leaq 0x8e132(%rip), %rcx     # 0xdb808
movl %edx, (%rcx)
movzwl 0x4e(%rsp), %ecx
movl %ecx, %edx
leaq 0x9016a(%rip), %rcx     # 0xdd850
movl (%rcx,%rdx,4), %esi
addl $0x1, %esi
leaq 0x9015d(%rip), %rcx     # 0xdd850
movl %esi, (%rcx,%rdx,4)
movq 0xa8(%rax), %rax
movzwl 0x4e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
addq $0x28, %rax
movq %rax, 0x8(%rsp)
movq 0x50(%rsp), %rsi
addq $0x58, %rsi
leaq 0x38(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0x59a50
movq 0x8(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x59a20
movq %rax, 0x30(%rsp)
jmp 0x4d7ee
movq 0x10(%rsp), %rax
leaq 0x8e0cc(%rip), %rcx     # 0xdb818
movl (%rcx), %edx
addl $0x1, %edx
leaq 0x8e0c0(%rip), %rcx     # 0xdb818
movl %edx, (%rcx)
movzwl 0x4e(%rsp), %ecx
movl %ecx, %edx
leaq 0x910e8(%rip), %rcx     # 0xde850
movl (%rcx,%rdx,4), %esi
addl $0x1, %esi
leaq 0x910db(%rip), %rcx     # 0xde850
movl %esi, (%rcx,%rdx,4)
leaq 0x8e08d(%rip), %rcx     # 0xdb80c
movl (%rcx), %edx
addl $0x1, %edx
leaq 0x8e081(%rip), %rcx     # 0xdb80c
movl %edx, (%rcx)
movzwl 0x4e(%rsp), %ecx
movl %ecx, %edx
leaq 0x904b5(%rip), %rcx     # 0xddc50
movl (%rcx,%rdx,4), %esi
addl $0x1, %esi
leaq 0x904a8(%rip), %rcx     # 0xddc50
movl %esi, (%rcx,%rdx,4)
movq 0xa8(%rax), %rax
movzwl 0x4e(%rsp), %ecx
movq (%rax,%rcx,8), %rax
addq $0x58, %rax
movq %rax, (%rsp)
movq 0x50(%rsp), %rsi
addq $0x58, %rsi
leaq 0x20(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0x59a50
movq (%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x59a20
movq %rax, 0x18(%rsp)
jmp 0x4d7f0
movb $0x0, 0x67(%rsp)
movb 0x67(%rsp), %al
andb $0x1, %al
addq $0x68, %rsp
retq