예제 #1
0
void cpu_thread::on_task()
{
	state -= cpu_flag::exit;

	g_tls_current_cpu_thread = this;

	// Check thread status
	while (!test(state, cpu_flag::exit + cpu_flag::dbg_global_stop))
	{
		// Check stop status
		if (!test(state & cpu_flag::stop))
		{
			try
			{
				cpu_task();
			}
			catch (cpu_flag _s)
			{
				state += _s;
			}
			catch (const std::exception&)
			{
				LOG_NOTICE(GENERAL, "\n%s", dump());
				throw;
			}

			state -= cpu_flag::ret;
			continue;
		}

		thread_ctrl::wait();
	}
}
예제 #2
0
void cpu_thread::on_task()
{
	state -= cpu_flag::exit;

	g_tls_current_cpu_thread = this;

	Emu.SendDbgCommand(DID_CREATE_THREAD, this);

	std::unique_lock<named_thread> lock(*this);

	// Check thread status
	while (!test(state & cpu_flag::exit))
	{
		CHECK_EMU_STATUS;

		// check stop status
		if (!test(state & cpu_flag::stop))
		{
			if (lock) lock.unlock();

			try
			{
				cpu_task();
			}
			catch (cpu_flag _s)
			{
				state += _s;
			}
			catch (const std::exception&)
			{
				LOG_NOTICE(GENERAL, "\n%s", dump());
				throw;
			}

			state -= cpu_flag::ret;
			continue;
		}

		if (!lock)
		{
			lock.lock();
			continue;
		}

		thread_ctrl::wait();
	}
}
예제 #3
0
void PPUThread::fast_call(u32 addr, u32 rtoc)
{
	auto old_PC = pc;
	auto old_stack = GPR[1];
	auto old_rtoc = GPR[2];
	auto old_LR = LR;
	auto old_task = std::move(custom_task);

	pc = addr;
	GPR[2] = rtoc;
	LR = Emu.GetCPUThreadStop();
	custom_task = nullptr;

	try
	{
		cpu_task();
	}
	catch (cpu_state _s)
	{
		state += _s;
		if (_s != cpu_state::ret) throw;
	}

	state -= cpu_state::ret;

	pc = old_PC;

	if (GPR[1] != old_stack) // GPR[1] shouldn't change
	{
		throw EXCEPTION("Stack inconsistency (addr=0x%x, rtoc=0x%x, SP=0x%llx, old=0x%llx)", addr, rtoc, GPR[1], old_stack);
	}

	GPR[2] = old_rtoc;
	LR = old_LR;
	custom_task = std::move(old_task);

	//if (custom_task)
	//{
	//	state += cpu_state::interrupt;
	//	handle_interrupt();
	//}
}
예제 #4
0
void ARMv7Thread::fast_call(u32 addr)
{
    if (!is_current())
    {
        throw EXCEPTION("Called from the wrong thread");
    }

    auto old_PC = PC;
    auto old_stack = SP;
    auto old_LR = LR;
    auto old_task = std::move(custom_task);

    PC = addr;
    LR = Emu.GetCPUThreadStop();
    custom_task = nullptr;

    try
    {
        cpu_task();
    }
    catch (CPUThreadReturn)
    {
    }

    m_state &= ~CPU_STATE_RETURN;

    PC = old_PC;

    if (SP != old_stack) // SP shouldn't change
    {
        throw EXCEPTION("Stack inconsistency (addr=0x%x, SP=0x%x, old=0x%x)", addr, SP, old_stack);
    }

    LR = old_LR;
    custom_task = std::move(old_task);
}