#include "stdafx.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/SPUDecoder.h"
#include "Emu/Cell/SPUInterpreter.h"
#include "Emu/Cell/SPUDisAsm.h"

SPUThread& GetCurrentSPUThread()
{
	PPCThread* thread = GetCurrentPPCThread();

	if(!thread || (thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU))
	{
		throw wxString("GetCurrentSPUThread: bad thread");
	}

	return *(SPUThread*)thread;
}

SPUThread::SPUThread(CPUThreadType type) : PPCThread(type)
{
	assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU);

	Reset();
}

SPUThread::~SPUThread()
{
}

void SPUThread::DoReset()
{
	PPCThread::DoReset();

	//reset regs
	memset(GPR, 0, sizeof(SPU_GPR_hdr) * 128);
}

void SPUThread::InitRegs()
{
	//GPR[1]._u64[0] = stack_point;
	GPR[3]._u64[1] = m_args[0];
	GPR[4]._u64[1] = m_args[1];
	GPR[5]._u64[1] = m_args[2];
	GPR[6]._u64[1] = m_args[3];

	dmac.ls_offset = m_offset;
	dmac.proxy_pos = 0;
	dmac.queue_pos = 0;

	SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP);
	SPU.Status.SetValue(SPU_STATUS_RUNNING);
	Prxy.QueryType.SetValue(0);
	MFC.CMDStatus.SetValue(0);
	PC = SPU.NPC.GetValue();
}

u64 SPUThread::GetFreeStackSize() const
{
	return (GetStackAddr() + GetStackSize()) - GPR[1]._u64[0];
}

void SPUThread::DoRun()
{
	switch(Ini.CPUDecoderMode.GetValue())
	{
	case 0:
		//m_dec = new SPUDecoder(*new SPUDisAsm());
	break;

	case 1:
	case 2:
		m_dec = new SPUDecoder(*new SPUInterpreter(*this));
	break;
	}
}

void SPUThread::DoResume()
{
}

void SPUThread::DoPause()
{
}

void SPUThread::DoStop()
{
	delete m_dec;
	m_dec = 0;
}
