project64/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp

283 lines
11 KiB
C++
Raw Normal View History

#include "stdafx.h"
2022-09-26 02:31:54 +00:00
2015-12-06 09:59:58 +00:00
#include "InterpreterCPU.h"
2017-08-18 05:08:22 +00:00
2022-09-26 02:31:54 +00:00
#include <Project64-core/Debugger.h>
#include <Project64-core/ExceptionHandler.h>
2015-12-06 09:59:58 +00:00
#include <Project64-core/N64System/Interpreter/InterpreterOps32.h>
2022-09-26 02:31:54 +00:00
#include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
#include <Project64-core/N64System/Mips/R4300iInstruction.h>
2022-09-26 02:31:54 +00:00
#include <Project64-core/N64System/N64System.h>
#include <Project64-core/N64System/SystemGlobals.h>
2015-12-19 23:50:17 +00:00
#include <Project64-core/Plugins/GFXPlugin.h>
2022-09-26 02:31:54 +00:00
#include <Project64-core/Plugins/Plugin.h>
2021-04-12 11:35:39 +00:00
R4300iOp::Func * CInterpreterCPU::m_R4300i_Opcode = nullptr;
void ExecuteInterpreterOps(uint32_t /*Cycles*/)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CInterpreterCPU::BuildCPU()
{
R4300iOp::m_TestTimer = false;
if (g_Settings->LoadBool(Game_32Bit))
{
m_R4300i_Opcode = R4300iOp32::BuildInterpreter();
}
else
{
m_R4300i_Opcode = R4300iOp::BuildInterpreter();
}
}
void CInterpreterCPU::InPermLoop()
{
if (EndOnPermLoop() &&
((g_Reg->STATUS_REGISTER & STATUS_IE) == 0 ||
2022-09-26 02:31:54 +00:00
(g_Reg->STATUS_REGISTER & STATUS_EXL) != 0 ||
(g_Reg->STATUS_REGISTER & STATUS_ERL) != 0 ||
(g_Reg->STATUS_REGISTER & 0xFF00) == 0))
{
2021-04-12 11:35:39 +00:00
if (g_Plugins->Gfx()->UpdateScreen != nullptr)
{
g_Plugins->Gfx()->UpdateScreen();
}
g_Notify->DisplayError(GS(MSG_PERM_LOOP));
g_System->CloseCpu();
}
else if (*g_NextTimer > 0)
{
g_SystemTimer->UpdateTimers();
*g_NextTimer = 0 - g_System->CountPerOp();
g_SystemTimer->UpdateTimers();
}
}
void CInterpreterCPU::ExecuteCPU()
{
WriteTrace(TraceN64System, TraceDebug, "Start");
bool & Done = g_System->m_EndEmulation;
PIPELINE_STAGE & PipelineStage = g_System->m_PipelineStage;
uint32_t & PROGRAM_COUNTER = *_PROGRAM_COUNTER;
R4300iOpcode & Opcode = R4300iOp::m_Opcode;
uint32_t & JumpToLocation = g_System->m_JumpToLocation;
bool & TestTimer = R4300iOp::m_TestTimer;
const int32_t & bDoSomething = g_SystemEvents->DoSomething();
uint32_t CountPerOp = g_System->CountPerOp();
int32_t & NextTimer = *g_NextTimer;
bool CheckTimer = false;
2015-11-14 22:08:30 +00:00
__except_try()
{
while (!Done)
{
if (!g_MMU->MemoryValue32(PROGRAM_COUNTER, Opcode.Value))
{
g_Reg->DoTLBReadMiss(PipelineStage == PIPELINE_STAGE_JUMP, PROGRAM_COUNTER);
PipelineStage = PIPELINE_STAGE_NORMAL;
continue;
}
2022-01-03 23:56:14 +00:00
if (HaveDebugger())
{
if (HaveExecutionBP() && g_Debugger->ExecutionBP(PROGRAM_COUNTER))
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
}
g_Debugger->CPUStepStarted(); // May set stepping ops/skip op
if (isStepping())
{
g_Debugger->WaitForStep();
}
if (SkipOp())
{
// Skip command if instructed by the debugger
g_Settings->SaveBool(Debugger_SkipOp, false);
PROGRAM_COUNTER += 4;
continue;
}
g_Debugger->CPUStep();
}
/* if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER < 0x80380000)
{
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iInstruction(*_PROGRAM_COUNTER, Opcode.Value).NameAndParam().c_str());
// WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s t9: %08X v1: %08X",*_PROGRAM_COUNTER,R4300iInstruction(*_PROGRAM_COUNTER, Opcode.Value).NameAndParam().c_str(),_GPR[0x19].UW[0],_GPR[0x03].UW[0]);
// WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType());
} */
2017-08-18 05:08:22 +00:00
m_R4300i_Opcode[Opcode.op]();
_GPR[0].DW = 0; // MIPS $zero hard-wired to 0
NextTimer -= CountPerOp;
2022-09-26 02:31:54 +00:00
if (CDebugSettings::HaveDebugger())
{
g_Debugger->CPUStepEnded();
}
2017-08-30 04:54:06 +00:00
PROGRAM_COUNTER += 4;
switch (PipelineStage)
{
case PIPELINE_STAGE_NORMAL:
break;
case PIPELINE_STAGE_DELAY_SLOT:
PipelineStage = PIPELINE_STAGE_JUMP;
break;
2022-09-26 02:31:54 +00:00
case PIPELINE_STAGE_PERMLOOP_DO_DELAY:
PipelineStage = PIPELINE_STAGE_PERMLOOP_DELAY_DONE;
break;
2022-09-26 02:31:54 +00:00
case PIPELINE_STAGE_JUMP:
CheckTimer = (JumpToLocation < PROGRAM_COUNTER - 4 || TestTimer);
PROGRAM_COUNTER = JumpToLocation;
PipelineStage = PIPELINE_STAGE_NORMAL;
if (CheckTimer)
2015-11-14 22:08:30 +00:00
{
TestTimer = false;
if (NextTimer < 0)
{
g_SystemTimer->TimerDone();
}
if (bDoSomething)
{
g_SystemEvents->ExecuteEvents();
}
}
break;
case PIPELINE_STAGE_PERMLOOP_DELAY_DONE:
PROGRAM_COUNTER = JumpToLocation;
PipelineStage = PIPELINE_STAGE_NORMAL;
CInterpreterCPU::InPermLoop();
g_SystemTimer->TimerDone();
if (bDoSomething)
{
g_SystemEvents->ExecuteEvents();
}
break;
default:
g_Notify->BreakPoint(__FILE__, __LINE__);
}
}
2015-11-14 22:08:30 +00:00
}
__except_catch()
{
g_Notify->FatalError(GS(MSG_UNKNOWN_MEM_ACTION));
}
WriteTrace(TraceN64System, TraceDebug, "Done");
}
void CInterpreterCPU::ExecuteOps(int32_t Cycles)
{
bool & Done = g_System->m_EndEmulation;
2022-09-26 02:31:54 +00:00
uint32_t & PROGRAM_COUNTER = *_PROGRAM_COUNTER;
R4300iOpcode & Opcode = R4300iOp::m_Opcode;
PIPELINE_STAGE & PipelineStage = g_System->m_PipelineStage;
uint32_t & JumpToLocation = g_System->m_JumpToLocation;
2022-09-26 02:31:54 +00:00
bool & TestTimer = R4300iOp::m_TestTimer;
const int32_t & DoSomething = g_SystemEvents->DoSomething();
uint32_t CountPerOp = g_System->CountPerOp();
bool CheckTimer = false;
__except_try()
{
while (!Done)
{
if (Cycles <= 0)
{
g_SystemTimer->UpdateTimers();
return;
}
if (g_MMU->MemoryValue32(PROGRAM_COUNTER, Opcode.Value))
{
/*if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER< 0x80380000)
{
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iInstruction(*_PROGRAM_COUNTER, Opcode.Value).NameAndParam().c_str());
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s t9: %08X v1: %08X",*_PROGRAM_COUNTER,R4300iInstruction(*_PROGRAM_COUNTER, Opcode.Value).NameAndParam().c_str(),_GPR[0x19].UW[0],_GPR[0x03].UW[0]);
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType());
}*/
/*if (PROGRAM_COUNTER > 0x80323000 && PROGRAM_COUNTER< 0x80380000)
{
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iInstruction(*_PROGRAM_COUNTER, Opcode.Value).NameAndParam().c_str());
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s t9: %08X v1: %08X",*_PROGRAM_COUNTER,R4300iInstruction(*_PROGRAM_COUNTER, Opcode.Value).NameAndParam().c_str(),_GPR[0x19].UW[0],_GPR[0x03].UW[0]);
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType());
}*/
m_R4300i_Opcode[Opcode.op]();
_GPR[0].DW = 0; /* MIPS $zero hard-wired to 0 */
Cycles -= CountPerOp;
*g_NextTimer -= CountPerOp;
/*static uint32_t TestAddress = 0x80077B0C, TestValue = 0, CurrentValue = 0;
if (g_MMU->MemoryValue32(TestAddress, TestValue))
{
if (TestValue != CurrentValue)
{
WriteTraceF(TraceError,"%X: %X changed (%s)",PROGRAM_COUNTER,TestAddress,R4300iInstruction(PROGRAM_COUNTER, m_Opcode.Value).NameAndParam().c_str());
CurrentValue = TestValue;
}
}*/
switch (PipelineStage)
{
case PIPELINE_STAGE_NORMAL:
PROGRAM_COUNTER += 4;
break;
case PIPELINE_STAGE_DELAY_SLOT:
PipelineStage = PIPELINE_STAGE_JUMP;
PROGRAM_COUNTER += 4;
break;
case PIPELINE_STAGE_PERMLOOP_DO_DELAY:
PipelineStage = PIPELINE_STAGE_PERMLOOP_DELAY_DONE;
PROGRAM_COUNTER += 4;
break;
case PIPELINE_STAGE_JUMP:
CheckTimer = (JumpToLocation < PROGRAM_COUNTER || TestTimer);
PROGRAM_COUNTER = JumpToLocation;
PipelineStage = PIPELINE_STAGE_NORMAL;
if (CheckTimer)
{
TestTimer = false;
if (*g_NextTimer < 0)
{
g_SystemTimer->TimerDone();
}
if (DoSomething)
2015-11-14 22:08:30 +00:00
{
g_SystemEvents->ExecuteEvents();
}
}
break;
case PIPELINE_STAGE_PERMLOOP_DELAY_DONE:
PROGRAM_COUNTER = JumpToLocation;
PipelineStage = PIPELINE_STAGE_NORMAL;
CInterpreterCPU::InPermLoop();
g_SystemTimer->TimerDone();
if (DoSomething)
{
g_SystemEvents->ExecuteEvents();
}
break;
default:
g_Notify->BreakPoint(__FILE__, __LINE__);
}
}
else
{
g_Reg->DoTLBReadMiss(PipelineStage == PIPELINE_STAGE_JUMP, PROGRAM_COUNTER);
PipelineStage = PIPELINE_STAGE_NORMAL;
}
}
}
__except_catch()
{
g_Notify->FatalError(GS(MSG_UNKNOWN_MEM_ACTION));
}
2015-11-14 22:08:30 +00:00
}