// CodeCache.cpp: implementation of the CCodeCache class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "archimedes.h"
#include "CodeCache.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


CCodeCache codeCache;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CCodeCache::CCodeCache()
{
	TRACE("construct CCodeCache \n");
}

CCodeCache::~CCodeCache()
{
	// delete every entry in the code cache
	
	std::map<uint32, NativeChunk*>::iterator codeIterator = addressToNativeCode.begin();
	do
	{	
		delete (*codeIterator).second; // delete native chunk
		codeIterator++;			// next entry
	}
	while( codeIterator != addressToNativeCode.end() );
}

void CCodeCache::testInvoke()
{
	TRACE("testing invokation !!!\n");
}

//
// add the native chunk to the cache, realted to the specified address
//

void CCodeCache::addCodeToCache(uint32 address, NativeChunk *aNativeChunk)
{
	// if there's already code entered for that address, delete it to avoid memory leaks
	if( addressToNativeCode[address] != NULL )
	{
		delete addressToNativeCode[address];
	}
	// add native chunk to hash table
	addressToNativeCode[address] = aNativeChunk;
}

//
// return TRUE if recompiled code exists for the given address
//

BOOL CCodeCache::recompiledCodeExists(uint32 address)
{
	if( addressToNativeCode[address] == NULL )
	{
		return FALSE;
	}
	else
	{
		return TRUE;
	}
}

//
// take a reference to a context and an address and execute the recompiled code
// that exists for that address, updating the context on return
// MUST check that code already exists using recompiledCodeExists()
//

void CCodeCache::invokeRecompiledCode(Context *aContext, uint32 address)
{

	// define function type
	typedef uint32 (*codeInvoker)(Context* argContext);
	// cast native code area to function
	codeInvoker callNativeCode = (codeInvoker)(addressToNativeCode[address]->area);
	// invoke native code area by calling that function
	uint32 returnVal = callNativeCode(aContext);

	// ??? act on returnVal

}
