view LightClone/Source/VirtualMachine.cpp @ 75:57c0ce406a68 tip

Add main menu
author koryspansel <koryspansel@bendbroadband.com>
date Tue, 18 Oct 2011 17:08:17 -0700
parents 1fe27776627e
children
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);

		PushFrame(nParameter, nInstructionPointer);
	}
	else

	if(nInstruction == Instruction_Return)
	{
		if(!pFrame)
		{
			// top level, program is complete
			return Action_Complete;
		}

		PopFrame();
	}

	return Action_None;
}

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

	while(pFrame)
	{
		Frame* pInstance = pFrame;
		pFrame = pInstance->pLast;

		kFrameAllocator.Free(pInstance);
	}
}

/*
 * 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()
{
	ASSERT(pFrame != NULL);
	nInstructionPointer = pFrame->nContinuation;

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