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
|
||||
{
|
||||
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 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!!!!");
|
||||
}
|
||||
|
||||
//long int runs=0;
|
||||
|
||||
void intBreakpoint(bool memcheck)
|
||||
{
|
||||
|
@ -127,39 +126,63 @@ void intCheckMemcheck()
|
|||
|
||||
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
|
||||
if (isBreakpointNeeded(cpuRegs.pc))
|
||||
intBreakpoint(false);
|
||||
|
||||
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
|
||||
cpuRegs.code = memRead32( cpuRegs.pc );
|
||||
cpuRegs.code = memRead32( pc );
|
||||
// Honestly I think this code is useless nowadays.
|
||||
#ifdef EXTRA_DEBUG
|
||||
if( IsDebugBuild )
|
||||
debugI();
|
||||
#endif
|
||||
|
||||
const OPCODE& opcode = GetCurrentInstruction();
|
||||
#if 0
|
||||
static long int runs = 0;
|
||||
//use this to find out what opcodes your game uses. very slow! (rama)
|
||||
//runs++;
|
||||
//if (runs > 1599999999){ //leave some time to startup the testgame
|
||||
// if (opcode.Name[0] == 'L') { //find all opcodes beginning with "L"
|
||||
// Console.WriteLn ("Load %s", opcode.Name);
|
||||
// }
|
||||
//}
|
||||
runs++;
|
||||
if (runs > 1599999999){ //leave some time to startup the testgame
|
||||
if (opcode.Name[0] == 'L') { //find all opcodes beginning with "L"
|
||||
Console.WriteLn ("Load %s", opcode.Name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Another method of instruction dumping:
|
||||
/*if( cpuRegs.cycle > 0x4f24d714 )
|
||||
{
|
||||
//CPU_LOG( "%s", disR5900Current.getCString());
|
||||
#if 0
|
||||
static long int print_me = 0;
|
||||
// Based on cycle
|
||||
// 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();
|
||||
opcode.disasm( disOut );
|
||||
disOut += '\n';
|
||||
disR5900Fasm(disOut, cpuRegs.code, pc);
|
||||
CPU_LOG( disOut.c_str() );
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
cpuBlockCycles += opcode.cycles;
|
||||
cpuRegs.pc += 4;
|
||||
|
||||
opcode.interpret();
|
||||
}
|
||||
|
@ -479,23 +502,48 @@ static void intEventTest()
|
|||
|
||||
static void intExecute()
|
||||
{
|
||||
try {
|
||||
if (g_SkipBiosHack) {
|
||||
do
|
||||
execI();
|
||||
while (cpuRegs.pc != EELOAD_START);
|
||||
eeloadReplaceOSDSYS();
|
||||
bool instruction_was_cancelled;
|
||||
enum ExecuteState {
|
||||
RESET,
|
||||
REPLACE_OSDSYS_DONE,
|
||||
GAME_STARTING_DONE
|
||||
};
|
||||
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) {
|
||||
do
|
||||
execI();
|
||||
while (cpuRegs.pc != ElfEntry);
|
||||
eeGameStarting();
|
||||
} else {
|
||||
while (true)
|
||||
execI();
|
||||
}
|
||||
} catch( Exception::ExitCpuExecute& ) { }
|
||||
catch( Exception::ExitCpuExecute& ) { }
|
||||
catch( Exception::CancelInstruction& ) { instruction_was_cancelled = true; }
|
||||
|
||||
// For example a tlb miss will throw an exception. Cpu must be resumed
|
||||
// to execute the handler
|
||||
} while (instruction_was_cancelled);
|
||||
}
|
||||
|
||||
static void intCheckExecutionState()
|
||||
|
|
|
@ -37,6 +37,12 @@ namespace Exception
|
|||
public:
|
||||
explicit ExitCpuExecute() { }
|
||||
};
|
||||
|
||||
class CancelInstruction
|
||||
{
|
||||
public:
|
||||
explicit CancelInstruction() { }
|
||||
};
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
|
@ -376,6 +376,9 @@ static __ri void vtlb_Miss(u32 addr,u32 mode)
|
|||
cpuTlbMissW(addr, cpuRegs.branch);
|
||||
else
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue