// File: gvaumour[P]cache-simulator/src/Cerebron.cc
// Function: CerebronPredictor::checkLazyMigration(CacheEntry*, unsigned long, bool, unsigned long, bool)
CacheEntry*
CerebronPredictor::checkLazyMigration(CacheEntry* current ,uint64_t set,bool inNVM, uint64_t index, bool isWrite)
{
	allocDecision des = activationFunction(isWrite , current->address , current->missPC);

	if( inNVM == false && des == ALLOCATE_IN_NVM)
	{
		//cl is SRAM , check whether we should migrate to NVM 
		if(simu_parameters.enableDatasetSpilling && m_isNVMbusy[set])
		{
			//reportSpilling(rap_current, current->address, false ,  inNVM);
			//stats_busyness_migrate_change++; //If NVM tab is busy , don't migrate
		}
		else
		{
			//Trigger Migration
			int id_assocNVM = evictPolicy(set, true);//Select LRU candidate from NVM cache
			//DPRINTF("DBAMBPredictor:: Migration Triggered from SRAM, index %ld, id_assoc %d \n" , index, id_assoc);

			CacheEntry* replaced_entry_NVM = m_tableNVM[set][id_assocNVM];
					
			/** Migration incurs one read and one extra write */ 
			replaced_entry_NVM->nbWrite++;
			current->nbRead++;
		
			/* Record the write error migration */ 
			Predictor::migrationRecording();
		
			reportMigration(current, false , isWrite);
		
			m_cache->triggerMigration(set, index , id_assocNVM , false);
			if(!m_isWarmup)
				stats_nbMigrations[true]++;


			current = replaced_entry_NVM;
		}

	}
	else if( des == ALLOCATE_IN_SRAM && inNVM == true)
	{
		//cl is in NVM , check whether we should migrate to SRAM 
			
		//If SRAM tab is busy , don't migrate
		if(simu_parameters.enableDatasetSpilling && m_isSRAMbusy[set])
		{
			//reportSpilling(rap_current, current->address, false ,  inNVM);
			//stats_busyness_migrate_change++; //If NVM tab is busy , don't migrate
		}
		else 
		{		
			int id_assocSRAM = evictPolicy(set, false);
		
			CacheEntry* replaced_entry_SRAM = m_tableSRAM[set][id_assocSRAM];

			/** Migration incurs one read and one extra write */ 
			replaced_entry_SRAM->nbWrite++;
			current->nbRead++;
			reportMigration( current, true , isWrite);
	
			m_cache->triggerMigration(set, id_assocSRAM , index , true);
		
			if(!m_isWarmup)
				stats_nbMigrations[false]++;

			current = replaced_entry_SRAM;		
		}

	}
	return current;
}

// Assembly:
subq $0x88, %rsp
movb %r9b, %al
movq %rdi, 0x80(%rsp)
movq %rsi, 0x78(%rsp)
movq %rdx, 0x70(%rsp)
andb $0x1, %cl
movb %cl, 0x6f(%rsp)
movq %r8, 0x60(%rsp)
andb $0x1, %al
movb %al, 0x5f(%rsp)
movq 0x80(%rsp), %rdi
movq %rdi, 0x10(%rsp)
movb 0x5f(%rsp), %al
movq 0x78(%rsp), %rcx
movq 0x8(%rcx), %rdx
movq 0x78(%rsp), %rcx
movq 0x20(%rcx), %rcx
andb $0x1, %al
movzbl %al, %esi
callq 0x7f00
movl %eax, 0x58(%rsp)
movb 0x6f(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0xb38d
cmpl $0x1, 0x58(%rsp)
jne 0xb38d
xorl %eax, %eax
leaq 0x88d9b(%rip), %rcx     # 0x93ff0
testb $0x1, 0x158(%rcx)
movb %al, 0xf(%rsp)
je 0xb290
movq 0x10(%rsp), %rdi
addq $0x110, %rdi            # imm = 0x110
movq 0x70(%rsp), %rsi
callq 0xfa90
movq %rax, 0x48(%rsp)
movq %rdx, 0x50(%rsp)
leaq 0x48(%rsp), %rdi
callq 0xfaf0
movb %al, 0xf(%rsp)
movb 0xf(%rsp), %al
testb $0x1, %al
jne 0xb29a
jmp 0xb29f
jmp 0xb388
movq 0x10(%rsp), %rdi
movq 0x70(%rsp), %rax
movl %eax, %esi
movq (%rdi), %rax
movl $0x1, %edx
callq *0x28(%rax)
movl %eax, %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x44(%rsp)
movq 0x10(%rax), %rdi
movq 0x70(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movslq 0x44(%rsp), %rsi
callq 0xf9c0
movq 0x10(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rax
movl 0x11c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x11c(%rax)
movq 0x78(%rsp), %rax
movl 0x120(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x120(%rax)
callq 0x56e70
movq 0x10(%rsp), %rdi
movq 0x78(%rsp), %rsi
movb 0x5f(%rsp), %al
xorl %edx, %edx
andb $0x1, %al
movzbl %al, %ecx
callq 0xc170
movq 0x10(%rsp), %rax
movq 0x70(%rax), %rdi
movq 0x70(%rsp), %rax
movl %eax, %esi
movq 0x60(%rsp), %rax
movl %eax, %edx
movl 0x44(%rsp), %ecx
xorl %r8d, %r8d
callq 0x3ac00
movq 0x10(%rsp), %rax
testb $0x1, 0x81(%rax)
jne 0xb37e
movq 0x10(%rsp), %rdi
addq $0x4c0, %rdi            # imm = 0x4C0
movl $0x1, %esi
callq 0xef90
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq 0x38(%rsp), %rax
movq %rax, 0x78(%rsp)
jmp 0xb4e2
cmpl $0x0, 0x58(%rsp)
jne 0xb4e0
movb 0x6f(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
jne 0xb4e0
xorl %eax, %eax
leaq 0x88c3d(%rip), %rcx     # 0x93ff0
testb $0x1, 0x158(%rcx)
movb %al, 0xe(%rsp)
je 0xb3ee
movq 0x10(%rsp), %rdi
addq $0xe8, %rdi
movq 0x70(%rsp), %rsi
callq 0xfa90
movq %rax, 0x28(%rsp)
movq %rdx, 0x30(%rsp)
leaq 0x28(%rsp), %rdi
callq 0xfaf0
movb %al, 0xe(%rsp)
movb 0xe(%rsp), %al
testb $0x1, %al
jne 0xb3f8
jmp 0xb3fd
jmp 0xb4de
movq 0x10(%rsp), %rdi
movq 0x70(%rsp), %rax
movl %eax, %esi
movq (%rdi), %rax
xorl %edx, %edx
callq *0x28(%rax)
movl %eax, %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x24(%rsp)
movq 0x8(%rax), %rdi
movq 0x70(%rsp), %rsi
callq 0xf9a0
movq %rax, %rdi
movslq 0x24(%rsp), %rsi
callq 0xf9c0
movq 0x10(%rsp), %rdi
movq (%rax), %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movl 0x11c(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x11c(%rax)
movq 0x78(%rsp), %rax
movl 0x120(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x120(%rax)
movq 0x78(%rsp), %rsi
movb 0x5f(%rsp), %al
movl $0x1, %edx
andb $0x1, %al
movzbl %al, %ecx
callq 0xc170
movq 0x10(%rsp), %rax
movq 0x70(%rax), %rdi
movq 0x70(%rsp), %rax
movl %eax, %esi
movl 0x24(%rsp), %edx
movq 0x60(%rsp), %rax
movl %eax, %ecx
movl $0x1, %r8d
callq 0x3ac00
movq 0x10(%rsp), %rax
testb $0x1, 0x81(%rax)
jne 0xb4d4
movq 0x10(%rsp), %rdi
addq $0x4c0, %rdi            # imm = 0x4C0
xorl %eax, %eax
movl %eax, %esi
callq 0xef90
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq 0x18(%rsp), %rax
movq %rax, 0x78(%rsp)
jmp 0xb4e0
jmp 0xb4e2
movq 0x78(%rsp), %rax
addq $0x88, %rsp
retq
nop