mirror of https://github.com/PCSX2/pcsx2.git
Merge pull request #350 from PCSX2/interpreter-tlb-handler
Interpreter tlb handler
This commit is contained in:
commit
ec976743d6
|
@ -28,7 +28,7 @@ extern char* disVU1MicroLF(u32 code, u32 pc);
|
||||||
|
|
||||||
namespace R5900
|
namespace R5900
|
||||||
{
|
{
|
||||||
void disR5900Fasm( std::string& output, u32 code, u32 pc, bool simplify);
|
void disR5900Fasm( std::string& output, u32 code, u32 pc, bool simplify = false);
|
||||||
|
|
||||||
extern const char * const GPR_REG[32];
|
extern const char * const GPR_REG[32];
|
||||||
extern const char * const COP0_REG[32];
|
extern const char * const COP0_REG[32];
|
||||||
|
|
|
@ -45,7 +45,6 @@ static void debugI()
|
||||||
if( cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1] ) Console.Error("R0 is not zero!!!!");
|
if( cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1] ) Console.Error("R0 is not zero!!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
//long int runs=0;
|
|
||||||
|
|
||||||
void intBreakpoint(bool memcheck)
|
void intBreakpoint(bool memcheck)
|
||||||
{
|
{
|
||||||
|
@ -127,39 +126,63 @@ void intCheckMemcheck()
|
||||||
|
|
||||||
static void execI()
|
static void execI()
|
||||||
{
|
{
|
||||||
|
// execI is called for every instruction so it must remains as light as possible.
|
||||||
|
// If you enable the next define, Interpreter will be much slower (around
|
||||||
|
// ~4fps on 3.9GHz Haswell vs ~8fps (even 10fps on dev build))
|
||||||
|
// Extra note: due to some cycle count issue PCSX2's internal debugger is
|
||||||
|
// not yet usable with the interpreter
|
||||||
|
//#define EXTRA_DEBUG
|
||||||
|
#ifdef EXTRA_DEBUG
|
||||||
// check if any breakpoints or memchecks are triggered by this instruction
|
// check if any breakpoints or memchecks are triggered by this instruction
|
||||||
if (isBreakpointNeeded(cpuRegs.pc))
|
if (isBreakpointNeeded(cpuRegs.pc))
|
||||||
intBreakpoint(false);
|
intBreakpoint(false);
|
||||||
|
|
||||||
intCheckMemcheck();
|
intCheckMemcheck();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u32 pc = cpuRegs.pc;
|
||||||
|
// We need to increase the pc before executing the memRead32. An exception could appears
|
||||||
|
// and it expects the PC counter to be pre-incremented
|
||||||
|
cpuRegs.pc += 4;
|
||||||
|
|
||||||
// interprete instruction
|
// interprete instruction
|
||||||
cpuRegs.code = memRead32( cpuRegs.pc );
|
cpuRegs.code = memRead32( pc );
|
||||||
|
// Honestly I think this code is useless nowadays.
|
||||||
|
#ifdef EXTRA_DEBUG
|
||||||
if( IsDebugBuild )
|
if( IsDebugBuild )
|
||||||
debugI();
|
debugI();
|
||||||
|
#endif
|
||||||
|
|
||||||
const OPCODE& opcode = GetCurrentInstruction();
|
const OPCODE& opcode = GetCurrentInstruction();
|
||||||
|
#if 0
|
||||||
|
static long int runs = 0;
|
||||||
//use this to find out what opcodes your game uses. very slow! (rama)
|
//use this to find out what opcodes your game uses. very slow! (rama)
|
||||||
//runs++;
|
runs++;
|
||||||
//if (runs > 1599999999){ //leave some time to startup the testgame
|
if (runs > 1599999999){ //leave some time to startup the testgame
|
||||||
// if (opcode.Name[0] == 'L') { //find all opcodes beginning with "L"
|
if (opcode.Name[0] == 'L') { //find all opcodes beginning with "L"
|
||||||
// Console.WriteLn ("Load %s", opcode.Name);
|
Console.WriteLn ("Load %s", opcode.Name);
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Another method of instruction dumping:
|
#if 0
|
||||||
/*if( cpuRegs.cycle > 0x4f24d714 )
|
static long int print_me = 0;
|
||||||
{
|
// Based on cycle
|
||||||
//CPU_LOG( "%s", disR5900Current.getCString());
|
// if( cpuRegs.cycle > 0x4f24d714 )
|
||||||
|
// Or dump from a particular PC (useful to debug handler/syscall)
|
||||||
|
if (cpuRegs.pc == 0x80000000) {
|
||||||
|
print_me = 2000;
|
||||||
|
}
|
||||||
|
if (print_me) {
|
||||||
|
print_me--;
|
||||||
disOut.clear();
|
disOut.clear();
|
||||||
opcode.disasm( disOut );
|
disR5900Fasm(disOut, cpuRegs.code, pc);
|
||||||
disOut += '\n';
|
|
||||||
CPU_LOG( disOut.c_str() );
|
CPU_LOG( disOut.c_str() );
|
||||||
}*/
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
cpuBlockCycles += opcode.cycles;
|
cpuBlockCycles += opcode.cycles;
|
||||||
cpuRegs.pc += 4;
|
|
||||||
|
|
||||||
opcode.interpret();
|
opcode.interpret();
|
||||||
}
|
}
|
||||||
|
@ -479,23 +502,48 @@ static void intEventTest()
|
||||||
|
|
||||||
static void intExecute()
|
static void intExecute()
|
||||||
{
|
{
|
||||||
try {
|
bool instruction_was_cancelled;
|
||||||
if (g_SkipBiosHack) {
|
enum ExecuteState {
|
||||||
do
|
RESET,
|
||||||
execI();
|
REPLACE_OSDSYS_DONE,
|
||||||
while (cpuRegs.pc != EELOAD_START);
|
GAME_STARTING_DONE
|
||||||
eeloadReplaceOSDSYS();
|
};
|
||||||
|
ExecuteState state = RESET;
|
||||||
|
do {
|
||||||
|
instruction_was_cancelled = false;
|
||||||
|
try {
|
||||||
|
// The execution was splited in three parts so it is easier to
|
||||||
|
// resume it after a cancelled instruction.
|
||||||
|
switch (state) {
|
||||||
|
case RESET:
|
||||||
|
if (g_SkipBiosHack) {
|
||||||
|
do
|
||||||
|
execI();
|
||||||
|
while (cpuRegs.pc != EELOAD_START);
|
||||||
|
eeloadReplaceOSDSYS();
|
||||||
|
}
|
||||||
|
state = REPLACE_OSDSYS_DONE;
|
||||||
|
|
||||||
|
case REPLACE_OSDSYS_DONE:
|
||||||
|
if (ElfEntry != 0xFFFFFFFF) {
|
||||||
|
do
|
||||||
|
execI();
|
||||||
|
while (cpuRegs.pc != ElfEntry);
|
||||||
|
eeGameStarting();
|
||||||
|
}
|
||||||
|
state = GAME_STARTING_DONE;
|
||||||
|
|
||||||
|
case GAME_STARTING_DONE:
|
||||||
|
while (true)
|
||||||
|
execI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ElfEntry != 0xFFFFFFFF) {
|
catch( Exception::ExitCpuExecute& ) { }
|
||||||
do
|
catch( Exception::CancelInstruction& ) { instruction_was_cancelled = true; }
|
||||||
execI();
|
|
||||||
while (cpuRegs.pc != ElfEntry);
|
// For example a tlb miss will throw an exception. Cpu must be resumed
|
||||||
eeGameStarting();
|
// to execute the handler
|
||||||
} else {
|
} while (instruction_was_cancelled);
|
||||||
while (true)
|
|
||||||
execI();
|
|
||||||
}
|
|
||||||
} catch( Exception::ExitCpuExecute& ) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intCheckExecutionState()
|
static void intCheckExecutionState()
|
||||||
|
|
|
@ -37,6 +37,12 @@ namespace Exception
|
||||||
public:
|
public:
|
||||||
explicit ExitCpuExecute() { }
|
explicit ExitCpuExecute() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CancelInstruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CancelInstruction() { }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -376,6 +376,9 @@ static __ri void vtlb_Miss(u32 addr,u32 mode)
|
||||||
cpuTlbMissW(addr, cpuRegs.branch);
|
cpuTlbMissW(addr, cpuRegs.branch);
|
||||||
else
|
else
|
||||||
cpuTlbMissR(addr, cpuRegs.branch);
|
cpuTlbMissR(addr, cpuRegs.branch);
|
||||||
|
|
||||||
|
// Exception handled. Current instruction need to be stopped
|
||||||
|
throw Exception::CancelInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The exception terminate the program on linux which is very annoying
|
// The exception terminate the program on linux which is very annoying
|
||||||
|
|
Loading…
Reference in New Issue