2010-05-23 10:05:41 +00:00
|
|
|
#include "stdafx.h"
|
2021-04-14 05:34:15 +00:00
|
|
|
#include <Project64-core/N64System/Mips/Register.h>
|
|
|
|
#include <Project64-core/N64System/N64System.h>
|
2015-12-06 09:59:58 +00:00
|
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
|
|
|
#include <Project64-core/Logging.h>
|
2015-11-13 06:34:57 +00:00
|
|
|
|
2022-09-05 07:17:51 +00:00
|
|
|
const char * CRegName::GPR[32] = {
|
|
|
|
"R0",
|
|
|
|
"AT",
|
|
|
|
"V0",
|
|
|
|
"V1",
|
|
|
|
"A0",
|
|
|
|
"A1",
|
|
|
|
"A2",
|
|
|
|
"A3",
|
|
|
|
"T0",
|
|
|
|
"T1",
|
|
|
|
"T2",
|
|
|
|
"T3",
|
|
|
|
"T4",
|
|
|
|
"T5",
|
|
|
|
"T6",
|
|
|
|
"T7",
|
|
|
|
"S0",
|
|
|
|
"S1",
|
|
|
|
"S2",
|
|
|
|
"S3",
|
|
|
|
"S4",
|
|
|
|
"S5",
|
|
|
|
"S6",
|
|
|
|
"S7",
|
|
|
|
"T8",
|
|
|
|
"T9",
|
|
|
|
"K0",
|
|
|
|
"K1",
|
|
|
|
"GP",
|
|
|
|
"SP",
|
|
|
|
"FP",
|
|
|
|
"RA"
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *CRegName::GPR_Hi[32] =
|
|
|
|
{
|
|
|
|
"r0.HI",
|
|
|
|
"at.HI",
|
|
|
|
"v0.HI",
|
|
|
|
"v1.HI",
|
|
|
|
"a0.HI",
|
|
|
|
"a1.HI",
|
|
|
|
"a2.HI",
|
|
|
|
"a3.HI",
|
|
|
|
"t0.HI",
|
|
|
|
"t1.HI",
|
|
|
|
"t2.HI",
|
|
|
|
"t3.HI",
|
|
|
|
"t4.HI",
|
|
|
|
"t5.HI",
|
|
|
|
"t6.HI",
|
|
|
|
"t7.HI",
|
|
|
|
"s0.HI",
|
|
|
|
"s1.HI",
|
|
|
|
"s2.HI",
|
|
|
|
"s3.HI",
|
|
|
|
"s4.HI",
|
|
|
|
"s5.HI",
|
|
|
|
"s6.HI",
|
|
|
|
"s7.HI",
|
|
|
|
"t8.HI",
|
|
|
|
"t9.HI",
|
|
|
|
"k0.HI",
|
|
|
|
"k1.HI",
|
|
|
|
"gp.HI",
|
|
|
|
"sp.HI",
|
|
|
|
"fp.HI",
|
|
|
|
"ra.HI"
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *CRegName::GPR_Lo[32] =
|
|
|
|
{
|
|
|
|
"r0.LO",
|
|
|
|
"at.LO",
|
|
|
|
"v0.LO",
|
|
|
|
"v1.LO",
|
|
|
|
"a0.LO",
|
|
|
|
"a1.LO",
|
|
|
|
"a2.LO",
|
|
|
|
"a3.LO",
|
|
|
|
"t0.LO",
|
|
|
|
"t1.LO",
|
|
|
|
"t2.LO",
|
|
|
|
"t3.LO",
|
|
|
|
"t4.LO",
|
|
|
|
"t5.LO",
|
|
|
|
"t6.LO",
|
|
|
|
"t7.LO",
|
|
|
|
"s0.LO",
|
|
|
|
"s1.LO",
|
|
|
|
"s2.LO",
|
|
|
|
"s3.LO",
|
|
|
|
"s4.LO",
|
|
|
|
"s5.LO",
|
|
|
|
"s6.LO",
|
|
|
|
"s7.LO",
|
|
|
|
"t8.LO",
|
|
|
|
"t9.LO",
|
|
|
|
"k0.LO",
|
|
|
|
"k1.LO",
|
|
|
|
"gp.LO",
|
|
|
|
"sp.LO",
|
|
|
|
"fp.LO",
|
|
|
|
"ra.LO"
|
|
|
|
};
|
|
|
|
|
|
|
|
const char * CRegName::Cop0[32] =
|
|
|
|
{
|
|
|
|
"Index",
|
|
|
|
"Random",
|
|
|
|
"EntryLo0",
|
|
|
|
"EntryLo1",
|
|
|
|
"Context",
|
|
|
|
"PageMask",
|
|
|
|
"Wired",
|
|
|
|
"Reg7",
|
|
|
|
"BadVAddr",
|
|
|
|
"Count",
|
|
|
|
"EntryHi",
|
|
|
|
"Compare",
|
|
|
|
"Status",
|
|
|
|
"Cause",
|
|
|
|
"EPC",
|
|
|
|
"PRId",
|
|
|
|
"Config",
|
|
|
|
"LLAddr",
|
|
|
|
"WatchLo",
|
|
|
|
"WatchHi",
|
|
|
|
"XContext",
|
|
|
|
"Reg21",
|
|
|
|
"Reg22",
|
|
|
|
"Reg23",
|
|
|
|
"Reg24",
|
|
|
|
"Reg25",
|
|
|
|
"ECC",
|
|
|
|
"CacheErr",
|
|
|
|
"TagLo",
|
|
|
|
"TagHi",
|
|
|
|
"ErrEPC",
|
|
|
|
"Reg31"
|
|
|
|
};
|
|
|
|
|
|
|
|
const char * CRegName::FPR[32] =
|
|
|
|
{
|
|
|
|
"F0",
|
|
|
|
"F1",
|
|
|
|
"F2",
|
|
|
|
"F3",
|
|
|
|
"F4",
|
|
|
|
"F5",
|
|
|
|
"F6",
|
|
|
|
"F7",
|
|
|
|
"F8",
|
|
|
|
"F9",
|
|
|
|
"F10",
|
|
|
|
"F11",
|
|
|
|
"F12",
|
|
|
|
"F13",
|
|
|
|
"F14",
|
|
|
|
"F15",
|
|
|
|
"F16",
|
|
|
|
"F17",
|
|
|
|
"F18",
|
|
|
|
"F19",
|
|
|
|
"F20",
|
|
|
|
"F21",
|
|
|
|
"F22",
|
|
|
|
"F23",
|
|
|
|
"F24",
|
|
|
|
"F25",
|
|
|
|
"F26",
|
|
|
|
"F27",
|
|
|
|
"F28",
|
|
|
|
"F29",
|
|
|
|
"F30",
|
|
|
|
"F31"
|
|
|
|
};
|
|
|
|
|
|
|
|
const char * CRegName::FPR_Ctrl[32] =
|
|
|
|
{
|
|
|
|
"Revision",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"Unknown",
|
|
|
|
"FCSR"
|
|
|
|
};
|
2008-09-18 03:15:49 +00:00
|
|
|
|
2021-04-12 11:35:39 +00:00
|
|
|
uint32_t * CSystemRegisters::_PROGRAM_COUNTER = nullptr;
|
|
|
|
MIPS_DWORD * CSystemRegisters::_GPR = nullptr;
|
|
|
|
MIPS_DWORD * CSystemRegisters::_FPR = nullptr;
|
|
|
|
uint32_t * CSystemRegisters::_CP0 = nullptr;
|
|
|
|
MIPS_DWORD * CSystemRegisters::_RegHI = nullptr;
|
|
|
|
MIPS_DWORD * CSystemRegisters::_RegLO = nullptr;
|
2015-11-08 20:45:41 +00:00
|
|
|
float ** CSystemRegisters::_FPR_S;
|
2010-06-04 06:25:07 +00:00
|
|
|
double ** CSystemRegisters::_FPR_D;
|
2021-04-12 11:35:39 +00:00
|
|
|
uint32_t * CSystemRegisters::_FPCR = nullptr;
|
|
|
|
uint32_t * CSystemRegisters::_LLBit = nullptr;
|
|
|
|
int32_t * CSystemRegisters::_RoundingModel = nullptr;
|
2010-06-04 06:25:07 +00:00
|
|
|
|
2015-11-08 20:45:41 +00:00
|
|
|
CP0registers::CP0registers(uint32_t * _CP0) :
|
2017-04-23 21:41:25 +00:00
|
|
|
INDEX_REGISTER(_CP0[0]),
|
|
|
|
RANDOM_REGISTER(_CP0[1]),
|
|
|
|
ENTRYLO0_REGISTER(_CP0[2]),
|
|
|
|
ENTRYLO1_REGISTER(_CP0[3]),
|
|
|
|
CONTEXT_REGISTER(_CP0[4]),
|
|
|
|
PAGE_MASK_REGISTER(_CP0[5]),
|
|
|
|
WIRED_REGISTER(_CP0[6]),
|
|
|
|
BAD_VADDR_REGISTER(_CP0[8]),
|
|
|
|
COUNT_REGISTER(_CP0[9]),
|
|
|
|
ENTRYHI_REGISTER(_CP0[10]),
|
|
|
|
COMPARE_REGISTER(_CP0[11]),
|
|
|
|
STATUS_REGISTER(_CP0[12]),
|
|
|
|
CAUSE_REGISTER(_CP0[13]),
|
|
|
|
EPC_REGISTER(_CP0[14]),
|
2022-07-18 09:26:52 +00:00
|
|
|
PREVID_REGISTER(_CP0[15]),
|
2017-04-23 21:41:25 +00:00
|
|
|
CONFIG_REGISTER(_CP0[16]),
|
|
|
|
TAGLO_REGISTER(_CP0[28]),
|
|
|
|
TAGHI_REGISTER(_CP0[29]),
|
|
|
|
ERROREPC_REGISTER(_CP0[30]),
|
|
|
|
FAKE_CAUSE_REGISTER(_CP0[32])
|
2008-09-18 03:15:49 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-11-08 20:45:41 +00:00
|
|
|
DisplayControlReg::DisplayControlReg(uint32_t * _DisplayProcessor) :
|
2017-04-23 21:41:25 +00:00
|
|
|
DPC_START_REG(_DisplayProcessor[0]),
|
|
|
|
DPC_END_REG(_DisplayProcessor[1]),
|
|
|
|
DPC_CURRENT_REG(_DisplayProcessor[2]),
|
|
|
|
DPC_STATUS_REG(_DisplayProcessor[3]),
|
|
|
|
DPC_CLOCK_REG(_DisplayProcessor[4]),
|
|
|
|
DPC_BUFBUSY_REG(_DisplayProcessor[5]),
|
|
|
|
DPC_PIPEBUSY_REG(_DisplayProcessor[6]),
|
|
|
|
DPC_TMEM_REG(_DisplayProcessor[7])
|
2008-09-18 03:15:49 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-12-18 23:55:05 +00:00
|
|
|
CRegisters::CRegisters(CN64System * System, CSystemEvents * SystemEvents) :
|
2017-04-23 21:41:25 +00:00
|
|
|
CP0registers(m_CP0),
|
2022-03-04 12:23:30 +00:00
|
|
|
RDRAMRegistersReg(m_RDRAM_Registers),
|
|
|
|
MIPSInterfaceReg(m_Mips_Interface),
|
2022-03-07 23:48:56 +00:00
|
|
|
VideoInterfaceReg(m_Video_Interface),
|
2017-04-23 21:41:25 +00:00
|
|
|
AudioInterfaceReg(m_Audio_Interface),
|
|
|
|
PeripheralInterfaceReg(m_Peripheral_Interface),
|
2022-01-04 05:41:52 +00:00
|
|
|
RDRAMInterfaceReg(m_RDRAM_Interface),
|
2022-01-24 12:43:10 +00:00
|
|
|
SPRegistersReg(m_SigProcessor_Interface),
|
2017-04-23 21:41:25 +00:00
|
|
|
DisplayControlReg(m_Display_ControlReg),
|
2022-03-21 04:34:59 +00:00
|
|
|
SerialInterfaceReg(m_SerialInterface),
|
2022-03-21 10:27:57 +00:00
|
|
|
DiskInterfaceReg(m_DiskInterface),
|
2017-04-23 21:41:25 +00:00
|
|
|
m_System(System),
|
|
|
|
m_SystemEvents(SystemEvents)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
|
|
|
Reset();
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRegisters::Reset()
|
|
|
|
{
|
2015-11-08 20:45:41 +00:00
|
|
|
m_FirstInterupt = true;
|
|
|
|
|
2015-11-13 06:34:57 +00:00
|
|
|
memset(m_GPR, 0, sizeof(m_GPR));
|
|
|
|
memset(m_CP0, 0, sizeof(m_CP0));
|
|
|
|
memset(m_FPR, 0, sizeof(m_FPR));
|
|
|
|
memset(m_FPCR, 0, sizeof(m_FPCR));
|
|
|
|
m_HI.DW = 0;
|
|
|
|
m_LO.DW = 0;
|
2016-01-17 06:34:05 +00:00
|
|
|
m_RoundingModel = FE_TONEAREST;
|
2015-11-08 20:45:41 +00:00
|
|
|
|
2015-11-13 06:34:57 +00:00
|
|
|
m_LLBit = 0;
|
2015-11-08 20:45:41 +00:00
|
|
|
|
2021-05-18 11:51:36 +00:00
|
|
|
// Reset system registers
|
2015-11-13 06:34:57 +00:00
|
|
|
memset(m_RDRAM_Interface, 0, sizeof(m_RDRAM_Interface));
|
|
|
|
memset(m_RDRAM_Registers, 0, sizeof(m_RDRAM_Registers));
|
|
|
|
memset(m_Mips_Interface, 0, sizeof(m_Mips_Interface));
|
|
|
|
memset(m_Video_Interface, 0, sizeof(m_Video_Interface));
|
|
|
|
memset(m_Display_ControlReg, 0, sizeof(m_Display_ControlReg));
|
|
|
|
memset(m_Audio_Interface, 0, sizeof(m_Audio_Interface));
|
|
|
|
memset(m_SigProcessor_Interface, 0, sizeof(m_SigProcessor_Interface));
|
|
|
|
memset(m_Peripheral_Interface, 0, sizeof(m_Peripheral_Interface));
|
|
|
|
memset(m_SerialInterface, 0, sizeof(m_SerialInterface));
|
2016-01-19 18:53:18 +00:00
|
|
|
memset(m_DiskInterface, 0, sizeof(m_DiskInterface));
|
2015-11-08 20:45:41 +00:00
|
|
|
|
|
|
|
m_AudioIntrReg = 0;
|
|
|
|
m_GfxIntrReg = 0;
|
|
|
|
m_RspIntrReg = 0;
|
|
|
|
|
|
|
|
FixFpuLocations();
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CRegisters::SetAsCurrentSystem()
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2015-11-08 20:45:41 +00:00
|
|
|
_PROGRAM_COUNTER = &m_PROGRAM_COUNTER;
|
|
|
|
_GPR = m_GPR;
|
|
|
|
_FPR = m_FPR;
|
|
|
|
_CP0 = m_CP0;
|
|
|
|
_RegHI = &m_HI;
|
|
|
|
_RegLO = &m_LO;
|
|
|
|
_FPR_S = m_FPR_S;
|
|
|
|
_FPR_D = m_FPR_D;
|
|
|
|
_FPCR = m_FPCR;
|
|
|
|
_LLBit = &m_LLBit;
|
|
|
|
_RoundingModel = &m_RoundingModel;
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CRegisters::CheckInterrupts()
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2016-02-10 00:59:46 +00:00
|
|
|
uint32_t mi_intr_reg = MI_INTR_REG, status_register;
|
2015-11-08 20:45:41 +00:00
|
|
|
if (!m_System->bFixedAudio() && CpuType() != CPU_SyncCores)
|
|
|
|
{
|
2016-02-10 00:59:46 +00:00
|
|
|
mi_intr_reg &= ~MI_INTR_AI;
|
|
|
|
mi_intr_reg |= (m_AudioIntrReg & MI_INTR_AI);
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
2016-02-10 00:59:46 +00:00
|
|
|
mi_intr_reg |= (m_RspIntrReg & MI_INTR_SP);
|
|
|
|
mi_intr_reg |= (m_GfxIntrReg & MI_INTR_DP);
|
|
|
|
if ((MI_INTR_MASK_REG & mi_intr_reg) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
|
|
|
FAKE_CAUSE_REGISTER |= CAUSE_IP2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FAKE_CAUSE_REGISTER &= ~CAUSE_IP2;
|
|
|
|
}
|
2016-02-10 00:59:46 +00:00
|
|
|
MI_INTR_REG = mi_intr_reg;
|
|
|
|
status_register = STATUS_REGISTER;
|
2015-11-08 20:45:41 +00:00
|
|
|
|
2016-02-10 00:59:46 +00:00
|
|
|
if ((status_register & STATUS_IE) == 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2016-02-10 00:59:46 +00:00
|
|
|
if ((status_register & STATUS_EXL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2016-02-10 00:59:46 +00:00
|
|
|
if ((status_register & STATUS_ERL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-10 00:59:46 +00:00
|
|
|
if ((status_register & FAKE_CAUSE_REGISTER & 0xFF00) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
|
|
|
if (m_FirstInterupt)
|
|
|
|
{
|
|
|
|
m_FirstInterupt = false;
|
|
|
|
if (g_Recompiler)
|
|
|
|
{
|
2015-11-13 06:34:57 +00:00
|
|
|
g_Recompiler->ClearRecompCode_Virt(0x80000000, 0x200, CRecompiler::Remove_InitialCode);
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
m_SystemEvents->QueueEvent(SysEvent_ExecuteInterrupt);
|
|
|
|
}
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2015-11-08 20:45:41 +00:00
|
|
|
void CRegisters::DoAddressError(bool DelaySlot, uint32_t BadVaddr, bool FromRead)
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2022-08-01 01:08:12 +00:00
|
|
|
if (BreakOnAddressError())
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2022-08-01 01:08:12 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (FromRead)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER = EXC_RADE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER = EXC_WADE;
|
|
|
|
}
|
|
|
|
BAD_VADDR_REGISTER = BadVaddr;
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2017-04-23 21:53:34 +00:00
|
|
|
void CRegisters::FixFpuLocations()
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
|
|
|
if ((STATUS_REGISTER & STATUS_FR) == 0)
|
|
|
|
{
|
2015-11-13 06:34:57 +00:00
|
|
|
for (int count = 0; count < 32; count++)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2017-04-25 08:04:00 +00:00
|
|
|
m_FPR_S[count] = &m_FPR[count & ~1].F[count & 1];
|
|
|
|
m_FPR_D[count] = &m_FPR[count & ~1].D;
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-04-23 21:41:25 +00:00
|
|
|
for (int count = 0; count < 32; count++)
|
|
|
|
{
|
|
|
|
m_FPR_S[count] = &m_FPR[count].F[0];
|
2015-11-08 20:45:41 +00:00
|
|
|
m_FPR_D[count] = &m_FPR[count].D;
|
|
|
|
}
|
|
|
|
}
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
|
2015-05-02 22:14:19 +00:00
|
|
|
void CRegisters::DoBreakException(bool DelaySlot)
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2015-11-13 06:34:57 +00:00
|
|
|
if ((STATUS_REGISTER & STATUS_EXL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("EXL set in break exception");
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
2015-11-13 06:34:57 +00:00
|
|
|
if ((STATUS_REGISTER & STATUS_ERL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("ERL set in break exception");
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CAUSE_REGISTER = EXC_BREAK;
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2019-12-16 20:15:26 +00:00
|
|
|
void CRegisters::DoTrapException(bool DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER = EXC_TRAP;
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-03-04 00:03:18 +00:00
|
|
|
void CRegisters::DoCopUnusableException(bool DelaySlot, int32_t Coprocessor)
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2015-11-13 06:34:57 +00:00
|
|
|
if ((STATUS_REGISTER & STATUS_EXL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("EXL set in break exception");
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
2015-11-13 06:34:57 +00:00
|
|
|
if ((STATUS_REGISTER & STATUS_ERL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("ERL set in break exception");
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CAUSE_REGISTER = EXC_CPU;
|
|
|
|
if (Coprocessor == 1)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= 0x10000000;
|
|
|
|
}
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2015-05-02 22:14:19 +00:00
|
|
|
bool CRegisters::DoIntrException(bool DelaySlot)
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2015-11-08 20:45:41 +00:00
|
|
|
if ((STATUS_REGISTER & STATUS_IE) == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((STATUS_REGISTER & STATUS_EXL) != 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((STATUS_REGISTER & STATUS_ERL) != 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-13 13:23:43 +00:00
|
|
|
if (GenerateLog() && LogExceptions() && !LogNoInterrupts())
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
LogMessage("%08X: Interrupt generated", m_PROGRAM_COUNTER);
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CAUSE_REGISTER = FAKE_CAUSE_REGISTER;
|
|
|
|
CAUSE_REGISTER |= EXC_INT;
|
|
|
|
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
return true;
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2022-09-19 02:42:08 +00:00
|
|
|
void CRegisters::DoIllegalInstructionException(bool DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER = EXC_II;
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
}
|
|
|
|
|
2022-09-05 07:05:13 +00:00
|
|
|
void CRegisters::DoOverflowException(bool DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER = EXC_OV;
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
}
|
|
|
|
|
2015-11-08 20:45:41 +00:00
|
|
|
void CRegisters::DoTLBReadMiss(bool DelaySlot, uint32_t BadVaddr)
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2015-11-08 20:45:41 +00:00
|
|
|
CAUSE_REGISTER = EXC_RMISS;
|
|
|
|
BAD_VADDR_REGISTER = BadVaddr;
|
|
|
|
CONTEXT_REGISTER &= 0xFF80000F;
|
|
|
|
CONTEXT_REGISTER |= (BadVaddr >> 9) & 0x007FFFF0;
|
|
|
|
ENTRYHI_REGISTER = (BadVaddr & 0xFFFFE000);
|
|
|
|
if ((STATUS_REGISTER & STATUS_EXL) == 0)
|
|
|
|
{
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
if (g_TLB->AddressDefined(BadVaddr))
|
|
|
|
{
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_PROGRAM_COUNTER = 0x80000000;
|
|
|
|
}
|
2020-03-04 00:03:18 +00:00
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (HaveDebugger())
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("TLBMiss - EXL set\nBadVaddr = %X\nAddress defined: %s", BadVaddr, g_TLB->AddressDefined(BadVaddr) ? "true" : "false").c_str());
|
2020-03-04 00:03:18 +00:00
|
|
|
}
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRegisters::DoTLBWriteMiss(bool DelaySlot, uint32_t BadVaddr)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER = EXC_WMISS;
|
|
|
|
BAD_VADDR_REGISTER = BadVaddr;
|
|
|
|
CONTEXT_REGISTER &= 0xFF80000F;
|
|
|
|
CONTEXT_REGISTER |= (BadVaddr >> 9) & 0x007FFFF0;
|
|
|
|
ENTRYHI_REGISTER = (BadVaddr & 0xFFFFE000);
|
|
|
|
if ((STATUS_REGISTER & STATUS_EXL) == 0)
|
|
|
|
{
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
if (g_TLB->AddressDefined(BadVaddr))
|
|
|
|
{
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_PROGRAM_COUNTER = 0x80000000;
|
|
|
|
}
|
2015-11-08 20:45:41 +00:00
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("TLBMiss - EXL set\nBadVaddr = %X\nAddress defined: %s", BadVaddr, g_TLB->AddressDefined(BadVaddr) ? "true" : "false").c_str());
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
|
|
|
}
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2015-05-02 22:14:19 +00:00
|
|
|
void CRegisters::DoSysCallException(bool DelaySlot)
|
2010-06-04 06:25:07 +00:00
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2015-11-13 06:34:57 +00:00
|
|
|
if ((STATUS_REGISTER & STATUS_EXL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("EXL set in syscall exception");
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
2015-11-13 06:34:57 +00:00
|
|
|
if ((STATUS_REGISTER & STATUS_ERL) != 0)
|
2015-11-08 20:45:41 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("ERL set in syscall exception");
|
2015-11-08 20:45:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CAUSE_REGISTER = EXC_SYSCALL;
|
|
|
|
if (DelaySlot)
|
|
|
|
{
|
|
|
|
CAUSE_REGISTER |= CAUSE_BD;
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EPC_REGISTER = m_PROGRAM_COUNTER;
|
|
|
|
}
|
|
|
|
STATUS_REGISTER |= STATUS_EXL;
|
|
|
|
m_PROGRAM_COUNTER = 0x80000180;
|
2017-08-18 05:08:22 +00:00
|
|
|
}
|