// File: iPapatsoris[P]Paging-Simulator/Simulator.cpp
// Function: Simulator::runWorkingSet(Address*, bool&)
void Simulator::runWorkingSet(Address *address, bool& processSwitch) {
	WorkingSet *workingSet = workingSetManager->getWorkingSetByProcess(address->getProcessId());
	if (processSwitch) {
		cout << "Restoring process " << address->getProcessId() << " working set:" << endl;
		processSwitch = false;
		bool change = false;
		this->restoreWorkingSetMemory(workingSet->getWorkingSet(), change);
		if (! change) {
			cout << "\tWorking set is already in memory" << endl;
		}
	}
	Address *victimAddress = NULL;
	workingSet->update(*address, &victimAddress);
	Address **mappingFrame = invertedPageTable.getFrameByAddress(*address);
	if (mappingFrame != NULL) {
		/* Page already in memory */
		this->checkWrite(address, *mappingFrame);
		delete address;
	}
	else {
		/* Page not in memory */
		statistics.pageFaults++;
		Address **freeFrame = invertedPageTable.getFreeFrame();
		if (freeFrame != NULL) {
			invertedPageTable.occupyFrame(freeFrame, address);
			printPageFault(NULL, address);
		}
		else {
			/* Remove a page not in working set.
			 * Prioritize the one just removed from working set (if any) */
			Address **victimFrame;
			if (victimAddress != NULL) {
				victimFrame = invertedPageTable.getFrameByAddress(*victimAddress);
			}
			else {
				victimFrame = invertedPageTable.getVictimFrameNotInSet(workingSet->getWorkingSet());
			}
			Address *toDelete = *victimFrame;
			*victimFrame = address;
			printPageFault(toDelete, address);
			if (toDelete->getDirty()) {
				cout << " Saving victim to disk.";
				statistics.diskWrites++;
			}
			delete toDelete;
		}
		cout << endl;
	}
	if (victimAddress != NULL) {
		delete victimAddress;
	}
	//workingSet->print();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x60(%rbp)
movq 0x50(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rdi
callq 0x3b10
movq -0x58(%rbp), %rdi
movl %eax, -0x24(%rbp)
leaq -0x24(%rbp), %rsi
callq 0x5ca0
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
testb $0x1, (%rax)
je 0x3488
movq 0x8be0(%rip), %rdi      # 0xbfd8
leaq 0x4d3a(%rip), %rsi      # 0x8139
callq 0x21e0
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rdi
callq 0x3b10
movq -0x68(%rbp), %rdi
movl %eax, %esi
callq 0x22f0
movq %rax, %rdi
leaq 0x4d26(%rip), %rsi      # 0x814c
callq 0x21e0
movq %rax, %rdi
movq 0x8b93(%rip), %rsi      # 0xbfc8
callq 0x2200
movq -0x18(%rbp), %rax
movb $0x0, (%rax)
movb $0x0, -0x25(%rbp)
movq -0x20(%rbp), %rdi
callq 0x5e90
movq -0x60(%rbp), %rdi
movq %rax, %rsi
leaq -0x25(%rbp), %rdx
callq 0x3800
testb $0x1, -0x25(%rbp)
jne 0x3486
movq 0x8b6d(%rip), %rdi      # 0xbfd8
leaq 0x4ce8(%rip), %rsi      # 0x815a
callq 0x21e0
movq %rax, %rdi
movq 0x8b47(%rip), %rsi      # 0xbfc8
callq 0x2200
jmp 0x3488
movq $0x0, -0x30(%rbp)
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq -0x30(%rbp), %rdx
callq 0x5cd0
movq -0x60(%rbp), %rdi
addq $0x38, %rdi
movq -0x10(%rbp), %rsi
callq 0x4b60
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x34f6
movq -0x60(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x38(%rbp), %rax
movq (%rax), %rdx
callq 0x3650
movq -0x10(%rbp), %rax
movq %rax, -0x70(%rbp)
cmpq $0x0, %rax
je 0x34f1
movq -0x70(%rbp), %rdi
callq 0x3a90
movq -0x70(%rbp), %rdi
callq 0x21d0
jmp 0x3608
movq -0x60(%rbp), %rdi
movl 0x5c(%rdi), %eax
addl $0x1, %eax
movl %eax, 0x5c(%rdi)
addq $0x38, %rdi
callq 0x4c00
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
je 0x353e
movq -0x60(%rbp), %rdi
addq $0x38, %rdi
movq -0x40(%rbp), %rsi
movq -0x10(%rbp), %rdx
callq 0x4c70
movq -0x10(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edi
callq 0x3720
jmp 0x35f5
cmpq $0x0, -0x30(%rbp)
je 0x355c
movq -0x60(%rbp), %rdi
addq $0x38, %rdi
movq -0x30(%rbp), %rsi
callq 0x4b60
movq %rax, -0x48(%rbp)
jmp 0x3581
movq -0x60(%rbp), %rax
addq $0x38, %rax
movq %rax, -0x78(%rbp)
movq -0x20(%rbp), %rdi
callq 0x5e90
movq -0x78(%rbp), %rdi
movq %rax, %rsi
callq 0x4c90
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rcx
movq -0x48(%rbp), %rax
movq %rcx, (%rax)
movq -0x50(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x3720
movq -0x50(%rbp), %rdi
callq 0x3af0
testb $0x1, %al
jne 0x35b3
jmp 0x35d3
movq 0x8a1e(%rip), %rdi      # 0xbfd8
leaq 0x4b60(%rip), %rsi      # 0x8121
callq 0x21e0
movq -0x60(%rbp), %rax
movl 0x60(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x60(%rax)
movq -0x50(%rbp), %rax
movq %rax, -0x80(%rbp)
cmpq $0x0, %rax
je 0x35f3
movq -0x80(%rbp), %rdi
callq 0x3a90
movq -0x80(%rbp), %rdi
callq 0x21d0
jmp 0x35f5
movq 0x89dc(%rip), %rdi      # 0xbfd8
movq 0x89c5(%rip), %rsi      # 0xbfc8
callq 0x2200
cmpq $0x0, -0x30(%rbp)
je 0x363a
movq -0x30(%rbp), %rax
movq %rax, -0x88(%rbp)
cmpq $0x0, %rax
je 0x3638
movq -0x88(%rbp), %rdi
callq 0x3a90
movq -0x88(%rbp), %rdi
callq 0x21d0
jmp 0x363a
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)