view LightClone/Source/VirtualMachine.cpp @ 54:95677f648a2c VirtualMachine Mk2

Refactored VirtualMachine
author koryspansel
date Fri, 30 Sep 2011 18:37:54 -0700
parents 4663f93aefc4
children dc1f4a668d50
line wrap: on
line source

/*
 * VirtualMachine.cpp
 */

#include "VirtualMachine.h"

/*
 * VirtualMachine
 */
VirtualMachine::VirtualMachine() : nInstructionPointer(0), pFrame(NULL)
{
	Clear();
}

/*
 * Step
 */
uint32 VirtualMachine::Step()
{
	const uint8 nInstruction = Advance();
	TRACE("Read instruction %d at address %d\n", nInstruction, nInstructionPointer - 1);
	
	if(nInstruction == Instruction_Action)
	{
		const uint8 nParameter = Advance();
		TRACE("  -- Action Decoded: %d\n", nParameter);

		return nParameter;
	}
	else

	if(nInstruction == Instruction_Call)
	{
		const uint8 nParameter = Advance();
		TRACE("  -- Call Decoded: %d\n", nParameter);

		const uint32 nFunction		= nParameter;
		const uint32 nContinuation	= nInstructionPointer;

		PushFrame(nFunction, nContinuation);
	}
	else

	if(nInstruction == Instruction_Return)
	{
		if(pFrame)
		{
			PopFrame();
		}
		else
		{
			// no frame to pop, we are done
			return Action_Complete;
		}
	}

	return Action_None;
}

/*
 * Reset
 */
void VirtualMachine::Reset()
{
	nInstructionPointer = 0;
}

/*
 * Clear
 */
void VirtualMachine::Clear()
{
	for(uint32 i = 0; i < Capacity; ++i)
	{
		nMemory[i] = 0;
	}
}

/*
 * GetMemorySize
 */
uint32 VirtualMachine::GetMemorySize() const
{
	return Capacity;
}

/*
 * GetMemoryPointer
 */
uint8* VirtualMachine::GetMemoryPointer()
{
	return &nMemory[0];
}

/*
 * PushFrame
 */
void VirtualMachine::PushFrame(uint32 nFunctionAddress, uint32 nContinuationAddress)
{
	Frame* pInstance = pFrame;

	while(pInstance)
	{
		if(pInstance->nAddress == nFunctionAddress && pInstance->nContinuation == nContinuationAddress)
		{
			break;
		}

		pInstance = pInstance->pLast;
	}

	if(pInstance)
	{
		while(pFrame && pFrame != pInstance)
		{
			Frame* pValue = pFrame;
			pFrame = pValue->pLast;

			kFrameAllocator.Free(pValue);
		}

		//ASSERT(pFrame != NULL);
	}
	else
	{
		pInstance					= kFrameAllocator.Allocate();
		pInstance->nAddress			= nFunctionAddress;
		pInstance->nContinuation	= nContinuationAddress;
		pInstance->pLast			= pFrame;

		pFrame = pInstance;
	}

	nInstructionPointer = nFunctionAddress;
}

/*
 * PopFrame
 */
void VirtualMachine::PopFrame()
{
	if(pFrame)
	{
		nInstructionPointer = pFrame->nContinuation;

		Frame* pInstance = pFrame;
		pFrame = pInstance->pLast;
		
		kFrameAllocator.Free(pInstance);
	}
	else
	{
	}
}