2012-12-19 09:30:18 +00:00
|
|
|
/****************************************************************************
|
|
|
|
* *
|
|
|
|
* Project 64 - A Nintendo 64 emulator. *
|
|
|
|
* http://www.pj64-emu.com/ *
|
|
|
|
* Copyright (C) 2012 Project64. All rights reserved. *
|
|
|
|
* *
|
|
|
|
* License: *
|
|
|
|
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
2010-05-25 09:15:19 +00:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
2010-05-31 00:21:08 +00:00
|
|
|
R4300iOp::Func * CInterpreterCPU::m_R4300i_Opcode = NULL;
|
|
|
|
|
2012-10-06 04:09:17 +00:00
|
|
|
void ExecuteInterpreterOps (DWORD /*Cycles*/)
|
2010-05-25 09:15:19 +00:00
|
|
|
{
|
2015-03-11 19:50:30 +00:00
|
|
|
g_Notify->BreakPoint(__FILEW__,__LINE__);
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
|
2015-03-29 15:02:27 +00:00
|
|
|
bool DelaySlotEffectsCompare (DWORD PC, DWORD Reg1, DWORD Reg2)
|
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
OPCODE Command;
|
|
|
|
|
2015-11-08 18:04:32 +00:00
|
|
|
if (!g_MMU->LW_VAddr(PC + 4, Command.Hex))
|
2015-03-29 15:02:27 +00:00
|
|
|
{
|
2015-03-04 09:36:08 +00:00
|
|
|
//g_Notify->DisplayError(L"Failed to load word 2");
|
2010-05-25 09:15:19 +00:00
|
|
|
//ExitThread(0);
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
|
2015-03-29 15:02:27 +00:00
|
|
|
switch (Command.op)
|
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
case R4300i_SPECIAL:
|
2015-03-29 15:02:27 +00:00
|
|
|
switch (Command.funct)
|
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
case R4300i_SPECIAL_SLL:
|
|
|
|
case R4300i_SPECIAL_SRL:
|
|
|
|
case R4300i_SPECIAL_SRA:
|
|
|
|
case R4300i_SPECIAL_SLLV:
|
|
|
|
case R4300i_SPECIAL_SRLV:
|
|
|
|
case R4300i_SPECIAL_SRAV:
|
|
|
|
case R4300i_SPECIAL_MFHI:
|
|
|
|
case R4300i_SPECIAL_MTHI:
|
|
|
|
case R4300i_SPECIAL_MFLO:
|
|
|
|
case R4300i_SPECIAL_MTLO:
|
|
|
|
case R4300i_SPECIAL_DSLLV:
|
|
|
|
case R4300i_SPECIAL_DSRLV:
|
|
|
|
case R4300i_SPECIAL_DSRAV:
|
|
|
|
case R4300i_SPECIAL_ADD:
|
|
|
|
case R4300i_SPECIAL_ADDU:
|
|
|
|
case R4300i_SPECIAL_SUB:
|
|
|
|
case R4300i_SPECIAL_SUBU:
|
|
|
|
case R4300i_SPECIAL_AND:
|
|
|
|
case R4300i_SPECIAL_OR:
|
|
|
|
case R4300i_SPECIAL_XOR:
|
|
|
|
case R4300i_SPECIAL_NOR:
|
|
|
|
case R4300i_SPECIAL_SLT:
|
|
|
|
case R4300i_SPECIAL_SLTU:
|
|
|
|
case R4300i_SPECIAL_DADD:
|
|
|
|
case R4300i_SPECIAL_DADDU:
|
|
|
|
case R4300i_SPECIAL_DSUB:
|
|
|
|
case R4300i_SPECIAL_DSUBU:
|
|
|
|
case R4300i_SPECIAL_DSLL:
|
|
|
|
case R4300i_SPECIAL_DSRL:
|
|
|
|
case R4300i_SPECIAL_DSRA:
|
|
|
|
case R4300i_SPECIAL_DSLL32:
|
|
|
|
case R4300i_SPECIAL_DSRL32:
|
|
|
|
case R4300i_SPECIAL_DSRA32:
|
2015-03-29 15:02:27 +00:00
|
|
|
if (Command.rd == 0)
|
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return false;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
if (Command.rd == Reg1 || Command.rd == Reg2)
|
2015-03-29 15:02:27 +00:00
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2010-05-25 09:15:19 +00:00
|
|
|
break;
|
|
|
|
case R4300i_SPECIAL_MULT:
|
|
|
|
case R4300i_SPECIAL_MULTU:
|
|
|
|
case R4300i_SPECIAL_DIV:
|
|
|
|
case R4300i_SPECIAL_DIVU:
|
|
|
|
case R4300i_SPECIAL_DMULT:
|
|
|
|
case R4300i_SPECIAL_DMULTU:
|
|
|
|
case R4300i_SPECIAL_DDIV:
|
|
|
|
case R4300i_SPECIAL_DDIVU:
|
|
|
|
break;
|
|
|
|
default:
|
2013-03-22 05:47:20 +00:00
|
|
|
if (g_Settings->LoadBool(Debugger_Enabled))
|
|
|
|
{
|
2015-10-25 11:40:21 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("Does %s effect Delay slot at %X?",R4300iOpcodeName(Command.Hex,PC+4), PC).ToUTF16().c_str());
|
2013-03-22 05:47:20 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_CP0:
|
2015-03-29 15:02:27 +00:00
|
|
|
switch (Command.rs)
|
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
case R4300i_COP0_MT: break;
|
|
|
|
case R4300i_COP0_MF:
|
2015-03-29 15:02:27 +00:00
|
|
|
if (Command.rt == 0)
|
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return false;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
if (Command.rt == Reg1 || Command.rt == Reg2)
|
2015-03-29 15:02:27 +00:00
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2010-05-25 09:15:19 +00:00
|
|
|
break;
|
|
|
|
default:
|
2015-03-29 15:02:27 +00:00
|
|
|
if ( (Command.rs & 0x10 ) != 0 )
|
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
switch (Command.funct)
|
2015-03-29 15:02:27 +00:00
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
case R4300i_COP0_CO_TLBR: break;
|
|
|
|
case R4300i_COP0_CO_TLBWI: break;
|
|
|
|
case R4300i_COP0_CO_TLBWR: break;
|
|
|
|
case R4300i_COP0_CO_TLBP: break;
|
|
|
|
default:
|
2013-03-22 05:47:20 +00:00
|
|
|
if (g_Settings->LoadBool(Debugger_Enabled))
|
|
|
|
{
|
2015-10-25 11:40:21 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("Does %s effect Delay slot at %X?\n6",R4300iOpcodeName(Command.Hex,PC+4), PC).ToUTF16().c_str());
|
2013-03-22 05:47:20 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-03-22 05:47:20 +00:00
|
|
|
if (g_Settings->LoadBool(Debugger_Enabled))
|
|
|
|
{
|
2015-10-25 11:40:21 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("Does %s effect Delay slot at %X?\n7",R4300iOpcodeName(Command.Hex,PC+4), PC).ToUTF16().c_str());
|
2013-03-22 05:47:20 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_CP1:
|
2015-03-29 15:02:27 +00:00
|
|
|
switch (Command.fmt)
|
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
case R4300i_COP1_MF:
|
2015-03-29 15:02:27 +00:00
|
|
|
if (Command.rt == 0)
|
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return false;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
if (Command.rt == Reg1 || Command.rt == Reg2)
|
2015-03-29 15:02:27 +00:00
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2010-05-25 09:15:19 +00:00
|
|
|
break;
|
|
|
|
case R4300i_COP1_CF: break;
|
|
|
|
case R4300i_COP1_MT: break;
|
|
|
|
case R4300i_COP1_CT: break;
|
|
|
|
case R4300i_COP1_S: break;
|
|
|
|
case R4300i_COP1_D: break;
|
|
|
|
case R4300i_COP1_W: break;
|
|
|
|
case R4300i_COP1_L: break;
|
|
|
|
default:
|
2013-03-22 05:47:20 +00:00
|
|
|
if (g_Settings->LoadBool(Debugger_Enabled))
|
|
|
|
{
|
2015-10-25 11:40:21 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("Does %s effect Delay slot at %X?",R4300iOpcodeName(Command.Hex,PC+4), PC).ToUTF16().c_str());
|
2013-03-22 05:47:20 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_ANDI:
|
|
|
|
case R4300i_ORI:
|
|
|
|
case R4300i_XORI:
|
|
|
|
case R4300i_LUI:
|
|
|
|
case R4300i_ADDI:
|
|
|
|
case R4300i_ADDIU:
|
|
|
|
case R4300i_SLTI:
|
|
|
|
case R4300i_SLTIU:
|
|
|
|
case R4300i_DADDI:
|
|
|
|
case R4300i_DADDIU:
|
|
|
|
case R4300i_LB:
|
|
|
|
case R4300i_LH:
|
|
|
|
case R4300i_LW:
|
|
|
|
case R4300i_LWL:
|
|
|
|
case R4300i_LWR:
|
|
|
|
case R4300i_LDL:
|
|
|
|
case R4300i_LDR:
|
|
|
|
case R4300i_LBU:
|
|
|
|
case R4300i_LHU:
|
|
|
|
case R4300i_LD:
|
|
|
|
case R4300i_LWC1:
|
|
|
|
case R4300i_LDC1:
|
2015-03-29 15:02:27 +00:00
|
|
|
if (Command.rt == 0)
|
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return false;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
if (Command.rt == Reg1 || Command.rt == Reg2)
|
2015-03-29 15:02:27 +00:00
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2010-05-25 09:15:19 +00:00
|
|
|
break;
|
|
|
|
case R4300i_CACHE: break;
|
|
|
|
case R4300i_SB: break;
|
|
|
|
case R4300i_SH: break;
|
|
|
|
case R4300i_SW: break;
|
|
|
|
case R4300i_SWR: break;
|
|
|
|
case R4300i_SWL: break;
|
|
|
|
case R4300i_SWC1: break;
|
|
|
|
case R4300i_SDC1: break;
|
|
|
|
case R4300i_SD: break;
|
|
|
|
default:
|
2013-03-22 05:47:20 +00:00
|
|
|
if (g_Settings->LoadBool(Debugger_Enabled))
|
|
|
|
{
|
2015-10-25 11:40:21 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("Does %s effect Delay slot at %X?",R4300iOpcodeName(Command.Hex,PC+4), PC).ToUTF16().c_str());
|
2013-03-22 05:47:20 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
return true;
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
2015-05-02 22:14:19 +00:00
|
|
|
return false;
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CInterpreterCPU::BuildCPU()
|
2012-09-30 12:24:07 +00:00
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
R4300iOp::m_TestTimer = false;
|
2012-09-30 12:24:07 +00:00
|
|
|
R4300iOp::m_NextInstruction = NORMAL;
|
|
|
|
R4300iOp::m_JumpToLocation = 0;
|
|
|
|
|
2012-11-17 01:02:04 +00:00
|
|
|
if (g_Settings->LoadBool(Game_32Bit))
|
2012-09-30 12:24:07 +00:00
|
|
|
{
|
|
|
|
m_R4300i_Opcode = R4300iOp32::BuildInterpreter();
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-09-30 12:24:07 +00:00
|
|
|
m_R4300i_Opcode = R4300iOp::BuildInterpreter();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CInterpreterCPU::InPermLoop()
|
2015-03-29 15:02:27 +00:00
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
// *** Changed ***/
|
2015-03-29 15:02:27 +00:00
|
|
|
//if (CPU_Type == CPU_SyncCores)
|
|
|
|
//{
|
|
|
|
// SyncRegisters.CP0[9] +=5;
|
|
|
|
//}
|
2010-05-25 09:15:19 +00:00
|
|
|
|
|
|
|
/* Interrupts enabled */
|
2012-11-17 02:18:14 +00:00
|
|
|
if (( g_Reg->STATUS_REGISTER & STATUS_IE ) == 0 ||
|
|
|
|
( g_Reg->STATUS_REGISTER & STATUS_EXL ) != 0 ||
|
|
|
|
( g_Reg->STATUS_REGISTER & STATUS_ERL ) != 0 ||
|
|
|
|
( g_Reg->STATUS_REGISTER & 0xFF00) == 0)
|
2010-10-23 18:53:01 +00:00
|
|
|
{
|
2015-03-29 15:02:27 +00:00
|
|
|
if (g_Plugins->Gfx()->UpdateScreen != NULL)
|
|
|
|
{
|
2015-03-29 21:58:51 +00:00
|
|
|
g_Plugins->Gfx()->UpdateScreen();
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
2010-10-23 18:53:01 +00:00
|
|
|
//CurrentFrame = 0;
|
|
|
|
//CurrentPercent = 0;
|
|
|
|
//DisplayFPS();
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->DisplayError(GS(MSG_PERM_LOOP));
|
2012-11-17 01:07:04 +00:00
|
|
|
g_System->CloseCpu();
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (*g_NextTimer > 0)
|
|
|
|
{
|
2012-11-29 11:23:35 +00:00
|
|
|
*g_NextTimer = 0 - g_System->CountPerOp();
|
2012-11-17 02:31:46 +00:00
|
|
|
g_SystemTimer->UpdateTimers();
|
2010-10-23 18:53:01 +00:00
|
|
|
}
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CInterpreterCPU::ExecuteCPU()
|
2010-05-31 00:21:08 +00:00
|
|
|
{
|
2012-11-17 01:07:04 +00:00
|
|
|
bool & Done = g_System->m_EndEmulation;
|
2015-11-08 20:45:41 +00:00
|
|
|
uint32_t & PROGRAM_COUNTER = *_PROGRAM_COUNTER;
|
2010-05-30 01:54:42 +00:00
|
|
|
OPCODE & Opcode = R4300iOp::m_Opcode;
|
|
|
|
DWORD & JumpToLocation = R4300iOp::m_JumpToLocation;
|
2015-05-02 22:14:19 +00:00
|
|
|
bool & TestTimer = R4300iOp::m_TestTimer;
|
2015-05-05 16:46:25 +00:00
|
|
|
const BOOL & bDoSomething= g_SystemEvents->DoSomething();
|
2012-11-29 11:23:35 +00:00
|
|
|
DWORD CountPerOp = g_System->CountPerOp();
|
2012-11-17 03:45:50 +00:00
|
|
|
int & NextTimer = *g_NextTimer;
|
2010-05-25 09:15:19 +00:00
|
|
|
|
|
|
|
__try
|
|
|
|
{
|
2015-03-29 15:02:27 +00:00
|
|
|
while (!Done)
|
2010-05-25 09:15:19 +00:00
|
|
|
{
|
2015-11-08 18:04:32 +00:00
|
|
|
if (g_MMU->LW_VAddr(PROGRAM_COUNTER, Opcode.Hex))
|
2010-05-25 09:15:19 +00:00
|
|
|
{
|
2010-06-07 02:23:58 +00:00
|
|
|
/*if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER< 0x80380000)
|
2010-05-25 09:15:19 +00:00
|
|
|
{
|
|
|
|
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER));
|
|
|
|
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s t9: %08X v1: %08X",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER),_GPR[0x19].UW[0],_GPR[0x03].UW[0]);
|
2012-11-17 03:45:50 +00:00
|
|
|
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType());
|
2010-05-25 09:15:19 +00:00
|
|
|
}*/
|
2010-05-31 00:21:08 +00:00
|
|
|
m_R4300i_Opcode[ Opcode.op ]();
|
2012-11-29 11:23:35 +00:00
|
|
|
NextTimer -= CountPerOp;
|
2010-05-25 09:15:19 +00:00
|
|
|
|
2010-05-30 01:54:42 +00:00
|
|
|
switch (R4300iOp::m_NextInstruction)
|
|
|
|
{
|
2010-05-25 09:15:19 +00:00
|
|
|
case NORMAL:
|
|
|
|
PROGRAM_COUNTER += 4;
|
|
|
|
break;
|
|
|
|
case DELAY_SLOT:
|
|
|
|
R4300iOp::m_NextInstruction = JUMP;
|
|
|
|
PROGRAM_COUNTER += 4;
|
|
|
|
break;
|
2010-07-05 11:29:46 +00:00
|
|
|
case PERMLOOP_DO_DELAY:
|
|
|
|
R4300iOp::m_NextInstruction = PERMLOOP_DELAY_DONE;
|
|
|
|
PROGRAM_COUNTER += 4;
|
|
|
|
break;
|
2010-05-25 09:15:19 +00:00
|
|
|
case JUMP:
|
|
|
|
{
|
|
|
|
BOOL CheckTimer = (JumpToLocation < PROGRAM_COUNTER || TestTimer);
|
|
|
|
PROGRAM_COUNTER = JumpToLocation;
|
|
|
|
R4300iOp::m_NextInstruction = NORMAL;
|
|
|
|
if (CheckTimer)
|
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
TestTimer = false;
|
2010-06-04 06:25:07 +00:00
|
|
|
if (NextTimer < 0)
|
2010-05-25 09:15:19 +00:00
|
|
|
{
|
2012-11-17 02:31:46 +00:00
|
|
|
g_SystemTimer->TimerDone();
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
2010-06-04 06:25:07 +00:00
|
|
|
if (bDoSomething)
|
|
|
|
{
|
2012-11-17 03:43:02 +00:00
|
|
|
g_SystemEvents->ExecuteEvents();
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
break;
|
|
|
|
case PERMLOOP_DELAY_DONE:
|
|
|
|
PROGRAM_COUNTER = JumpToLocation;
|
|
|
|
R4300iOp::m_NextInstruction = NORMAL;
|
2012-09-30 12:24:07 +00:00
|
|
|
CInterpreterCPU::InPermLoop();
|
2012-11-17 02:31:46 +00:00
|
|
|
g_SystemTimer->TimerDone();
|
2010-07-05 11:29:46 +00:00
|
|
|
if (bDoSomething)
|
|
|
|
{
|
2012-11-17 03:43:02 +00:00
|
|
|
g_SystemEvents->ExecuteEvents();
|
2010-07-05 11:29:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2015-03-11 19:50:30 +00:00
|
|
|
g_Notify->BreakPoint(__FILEW__,__LINE__);
|
2010-05-25 09:15:19 +00:00
|
|
|
}
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-11-17 02:18:14 +00:00
|
|
|
g_Reg->DoTLBReadMiss(R4300iOp::m_NextInstruction == JUMP,PROGRAM_COUNTER);
|
2010-05-25 09:15:19 +00:00
|
|
|
R4300iOp::m_NextInstruction = NORMAL;
|
|
|
|
}
|
|
|
|
}
|
2015-03-29 15:02:27 +00:00
|
|
|
} __except( g_MMU->MemoryFilter( GetExceptionCode(), GetExceptionInformation()) )
|
|
|
|
{
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->DisplayError(GS(MSG_UNKNOWN_MEM_ACTION));
|
2010-05-25 09:15:19 +00:00
|
|
|
ExitThread(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-31 00:21:08 +00:00
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CInterpreterCPU::ExecuteOps(int Cycles)
|
2010-05-31 00:21:08 +00:00
|
|
|
{
|
2012-11-17 01:07:04 +00:00
|
|
|
bool & Done = g_System->m_EndEmulation;
|
2015-11-08 20:45:41 +00:00
|
|
|
uint32_t & PROGRAM_COUNTER = *_PROGRAM_COUNTER;
|
2010-05-31 00:21:08 +00:00
|
|
|
OPCODE & Opcode = R4300iOp::m_Opcode;
|
|
|
|
DWORD & JumpToLocation = R4300iOp::m_JumpToLocation;
|
2015-05-02 22:14:19 +00:00
|
|
|
bool & TestTimer = R4300iOp::m_TestTimer;
|
2015-05-05 22:49:06 +00:00
|
|
|
const BOOL & DoSomething = g_SystemEvents->DoSomething();
|
2012-11-29 11:23:35 +00:00
|
|
|
DWORD CountPerOp = g_System->CountPerOp();
|
2010-05-31 00:21:08 +00:00
|
|
|
|
|
|
|
__try
|
|
|
|
{
|
2015-03-29 15:02:27 +00:00
|
|
|
while (!Done)
|
2010-05-31 00:21:08 +00:00
|
|
|
{
|
|
|
|
if (Cycles <= 0)
|
|
|
|
{
|
2012-11-17 02:31:46 +00:00
|
|
|
g_SystemTimer->UpdateTimers();
|
2010-05-31 00:21:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-08 18:04:32 +00:00
|
|
|
if (g_MMU->LW_VAddr(PROGRAM_COUNTER, Opcode.Hex))
|
2010-05-31 00:21:08 +00:00
|
|
|
{
|
2010-06-07 02:23:58 +00:00
|
|
|
/*if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER< 0x80380000)
|
|
|
|
{
|
|
|
|
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER));
|
|
|
|
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s t9: %08X v1: %08X",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER),_GPR[0x19].UW[0],_GPR[0x03].UW[0]);
|
2012-11-17 03:45:50 +00:00
|
|
|
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType());
|
2010-06-07 02:23:58 +00:00
|
|
|
}*/
|
2010-05-31 00:21:08 +00:00
|
|
|
/*if (PROGRAM_COUNTER > 0x80323000 && PROGRAM_COUNTER< 0x80380000)
|
|
|
|
{
|
|
|
|
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER));
|
|
|
|
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s t9: %08X v1: %08X",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER),_GPR[0x19].UW[0],_GPR[0x03].UW[0]);
|
2012-11-17 03:45:50 +00:00
|
|
|
//WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType());
|
2010-07-05 11:29:46 +00:00
|
|
|
}*/
|
|
|
|
m_R4300i_Opcode[ Opcode.op ]();
|
keep $zero overwrite prevention to a single location in CPU loop
In both the 32- and the 64-bit interpreters, ADDI, LUI, LB, LW, LWU, LL, SLLV all check if the destination register specifier is 0, when none of the other interpreter ops do. Actually, none of these 7 need to really check it either, since handling $zero overwrite is already managed in a single location in the main interpreter loop.
2015-03-08 23:29:41 +00:00
|
|
|
_GPR[0].DW = 0; /* MIPS $zero hard-wired to 0 */
|
2010-07-05 11:29:46 +00:00
|
|
|
|
2012-11-29 11:23:35 +00:00
|
|
|
Cycles -= CountPerOp;
|
|
|
|
*g_NextTimer -= CountPerOp;
|
2010-05-31 00:21:08 +00:00
|
|
|
|
2010-06-29 02:11:22 +00:00
|
|
|
/*static DWORD TestAddress = 0x80077B0C, TestValue = 0, CurrentValue = 0;
|
2012-11-17 01:18:00 +00:00
|
|
|
if (g_MMU->LW_VAddr(TestAddress, TestValue))
|
2010-06-14 21:14:58 +00:00
|
|
|
{
|
|
|
|
if (TestValue != CurrentValue)
|
|
|
|
{
|
|
|
|
WriteTraceF(TraceError,"%X: %X changed (%s)",PROGRAM_COUNTER,TestAddress,R4300iOpcodeName(m_Opcode.Hex,PROGRAM_COUNTER) );
|
|
|
|
CurrentValue = TestValue;
|
|
|
|
}
|
2010-06-29 02:11:22 +00:00
|
|
|
}*/
|
2010-06-14 21:14:58 +00:00
|
|
|
|
2010-05-31 00:21:08 +00:00
|
|
|
switch (R4300iOp::m_NextInstruction)
|
|
|
|
{
|
|
|
|
case NORMAL:
|
|
|
|
PROGRAM_COUNTER += 4;
|
|
|
|
break;
|
|
|
|
case DELAY_SLOT:
|
|
|
|
R4300iOp::m_NextInstruction = JUMP;
|
|
|
|
PROGRAM_COUNTER += 4;
|
|
|
|
break;
|
2010-07-05 11:29:46 +00:00
|
|
|
case PERMLOOP_DO_DELAY:
|
|
|
|
R4300iOp::m_NextInstruction = PERMLOOP_DELAY_DONE;
|
|
|
|
PROGRAM_COUNTER += 4;
|
|
|
|
break;
|
2010-05-31 00:21:08 +00:00
|
|
|
case JUMP:
|
|
|
|
{
|
|
|
|
BOOL CheckTimer = (JumpToLocation < PROGRAM_COUNTER || TestTimer);
|
|
|
|
PROGRAM_COUNTER = JumpToLocation;
|
|
|
|
R4300iOp::m_NextInstruction = NORMAL;
|
|
|
|
if (CheckTimer)
|
|
|
|
{
|
2015-05-02 22:14:19 +00:00
|
|
|
TestTimer = false;
|
|
|
|
if (*g_NextTimer < 0)
|
|
|
|
{
|
2012-11-17 02:31:46 +00:00
|
|
|
g_SystemTimer->TimerDone();
|
2010-05-31 00:21:08 +00:00
|
|
|
}
|
2010-06-04 06:25:07 +00:00
|
|
|
if (DoSomething)
|
|
|
|
{
|
2012-11-17 03:43:02 +00:00
|
|
|
g_SystemEvents->ExecuteEvents();
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
2010-05-31 00:21:08 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
break;
|
|
|
|
case PERMLOOP_DELAY_DONE:
|
|
|
|
PROGRAM_COUNTER = JumpToLocation;
|
|
|
|
R4300iOp::m_NextInstruction = NORMAL;
|
2012-09-30 12:24:07 +00:00
|
|
|
CInterpreterCPU::InPermLoop();
|
2012-11-17 02:31:46 +00:00
|
|
|
g_SystemTimer->TimerDone();
|
2010-07-05 11:29:46 +00:00
|
|
|
if (DoSomething)
|
|
|
|
{
|
2012-11-17 03:43:02 +00:00
|
|
|
g_SystemEvents->ExecuteEvents();
|
2010-07-05 11:29:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2015-03-11 19:50:30 +00:00
|
|
|
g_Notify->BreakPoint(__FILEW__,__LINE__);
|
2010-05-31 00:21:08 +00:00
|
|
|
}
|
2015-03-29 15:02:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-11-17 02:18:14 +00:00
|
|
|
g_Reg->DoTLBReadMiss(R4300iOp::m_NextInstruction == JUMP,PROGRAM_COUNTER);
|
2010-05-31 00:21:08 +00:00
|
|
|
R4300iOp::m_NextInstruction = NORMAL;
|
|
|
|
}
|
|
|
|
}
|
2015-03-29 15:02:27 +00:00
|
|
|
} __except( g_MMU->MemoryFilter( GetExceptionCode(), GetExceptionInformation()) )
|
|
|
|
{
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->DisplayError(GS(MSG_UNKNOWN_MEM_ACTION));
|
2010-05-31 00:21:08 +00:00
|
|
|
ExitThread(0);
|
|
|
|
}
|
|
|
|
}
|