view LightClone/Source/VirtualMachine.cpp @ 48:4663f93aefc4

Tracing
author koryspansel
date Fri, 23 Sep 2011 11:50:59 -0700
parents b60cbf3fa894
children 95677f648a2c
line wrap: on
line source

/*
 * VirtualMachine.cpp
 */

#include "VirtualMachine.h"

/*
 * VirtualMachine
 */
VirtualMachine::VirtualMachine() : nInstructionPointer(0), nFunctionCount(0)
{
	ClearMemory();
}

/*
 * Step
 */
uint32 VirtualMachine::Step()
{
	// decode and validate instruction pointer function and offset
	const uint8 nSourceFunction	= DecodeAddressFunction(nInstructionPointer);
	const uint8 nSourceOffset	= DecodeAddressOffset(nInstructionPointer);

	if(nSourceFunction < nFunctionCount && nSourceOffset <= kFunction[nSourceFunction].nSize)
	{
		TRACE("Reading address %d\n", nInstructionPointer);

		// read the next instruction
		const uint8 nInstruction	= Read();
		const uint8 nParameter		= Read();

		TRACE("Decoded I:%d P:%d\n", nInstruction, nParameter);

		if(nInstruction == Instruction_None)
		{
			return Action_Default;
		}
		else

		if(nInstruction == Instruction_Action)
		{
			// action instruction, the parameter is the action
			TRACE("  -- Action Decoded: %d\n", nParameter);
			return nParameter;
		}
		else
	
		if(nInstruction == Instruction_Call)
		{
			TRACE("  -- Call Decoded: %d\n", nParameter);

			// set instruction pointer to destination
			if(nParameter < nFunctionCount)
			{
				const uint8 nDestinationSize = kFunction[nParameter].nSize;

				// insert continuation jump into destination function
				nMemory[nParameter * FunctionStride + nDestinationSize + 0] = Instruction_Jump;
				nMemory[nParameter * FunctionStride + nDestinationSize + 1] = nInstructionPointer;

				TRACE("       - Inserting continuation\n");
				TRACE("         Instruction: %d\n", Instruction_Jump);
				TRACE("         Destination: %d\n", nInstructionPointer);

				// update instruction pointer to destination address
				nInstructionPointer = nParameter * FunctionStride;

				// signal that we're not yet done
				return Action_Default;
			}
		}
		else

		if(nInstruction == Instruction_Jump)
		{
			TRACE("  -- Jump Decoded: %d\n", nParameter);

			// decode and validate destination function and offset
			const uint8 nDestinationFunction	= DecodeAddressFunction(nParameter);
			const uint8 nDestinationOffset		= DecodeAddressOffset(nParameter);

			TRACE("       - Function: %d\n", nDestinationFunction);
			TRACE("       - Offset  : %d\n", nDestinationOffset);

			// set instruction pointer to destination
			if(nDestinationFunction < nFunctionCount && nDestinationOffset <= kFunction[nDestinationFunction].nSize)
			{
				// update instruction pointer to destination address
				nInstructionPointer = nParameter;

				// signal that we're not yet done
				return Action_Default;
			}
		}
	}

	return Action_Complete;
}

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

/*
 * SetMemory
 */
bool VirtualMachine::SetMemory(uint8 nFunction, const uint8* pData, uint8 nSize)
{
	if(nFunction < nFunctionCount)
	{
		const uint8 nFunctionAddress	= kFunction[nFunction].nAddress;
		const uint8 nFunctionSize		= kFunction[nFunction].nSize;

		for(uint8 nOffset = 0; nOffset < Min(nFunctionSize, nSize); ++nOffset)
		{
			nMemory[nFunctionAddress + nOffset] = pData[nOffset];
		}

		return true;
	}

	return false;
}

/*
 * ClearMemory
 */
void VirtualMachine::ClearMemory()
{
	for(uint8 nFunction = 0; nFunction < MaximumFunctionCount; ++nFunction)
	{
		for(uint8 nLocation = 0; nLocation < MaximumInstructionCount; ++nLocation)
		{
			nMemory[nFunction * FunctionStride + nLocation] = Instruction_None;
		}

		nMemory[nFunction * FunctionStride + FunctionStride - ContinuationInstructionSize + 0] = Instruction_Jump;
		nMemory[nFunction * FunctionStride + FunctionStride - ContinuationInstructionSize + 1] = 0;

	}
}

/*
 * AddFunction
 */
bool VirtualMachine::AddFunction(uint8 nFunction, uint8 nSize)
{
	if(nFunctionCount + 1 < MaximumFunctionCount)
	{
		kFunction[nFunctionCount].nAddress	= nFunctionCount * FunctionStride;
		kFunction[nFunctionCount].nSize		= nSize * 2;

		++nFunctionCount;

		return true;
	}

	return false;
}

/*
 * RemoveAllFunctions
 */
void VirtualMachine::RemoveAllFunctions()
{
	nFunctionCount = 0;
}

/*
 * GetFunctionSize
 */
uint32 VirtualMachine::GetFunctionSize(uint32 nIndex) const
{
	return nIndex < nFunctionCount ? kFunction[nIndex].nSize : 0;
}

/*
 * GetFunctionMemory
 */
uint8* VirtualMachine::GetFunctionMemory(uint32 nIndex)
{
	return nIndex < nFunctionCount ? &nMemory[kFunction[nIndex].nAddress] : 0;
}