2010-05-23 10:05:41 +00:00
# include "stdafx.h"
2022-10-10 00:22:17 +00:00
# include <Project64-core/Logging.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>
2023-01-29 23:37:51 +00:00
# include <fenv.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 " ,
2022-10-10 00:22:17 +00:00
" RA " ,
2022-09-05 07:17:51 +00:00
} ;
2022-10-10 00:22:17 +00:00
const char * CRegName : : GPR_Hi [ 32 ] = {
2022-09-05 07:17:51 +00:00
" 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 " ,
2022-10-10 00:22:17 +00:00
" ra.HI " ,
2022-09-05 07:17:51 +00:00
} ;
2022-10-10 00:22:17 +00:00
const char * CRegName : : GPR_Lo [ 32 ] = {
2022-09-05 07:17:51 +00:00
" 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 " ,
2022-10-10 00:22:17 +00:00
" ra.LO " ,
2022-09-05 07:17:51 +00:00
} ;
2022-10-10 00:22:17 +00:00
const char * CRegName : : Cop0 [ 32 ] = {
2022-09-05 07:17:51 +00:00
" 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 " ,
2022-10-10 00:22:17 +00:00
" Reg31 " ,
2022-09-05 07:17:51 +00:00
} ;
2022-10-10 00:22:17 +00:00
const char * CRegName : : FPR [ 32 ] = {
2022-09-05 07:17:51 +00:00
" 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 " ,
2022-10-10 00:22:17 +00:00
" F31 " ,
2022-09-05 07:17:51 +00:00
} ;
2022-10-10 00:22:17 +00:00
const char * CRegName : : FPR_Ctrl [ 32 ] = {
2022-09-05 07:17:51 +00:00
" 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 " ,
2022-10-10 00:22:17 +00:00
" FCSR " ,
2022-09-05 07:17:51 +00:00
} ;
2008-09-18 03:15:49 +00:00
2022-10-10 00:22:17 +00:00
uint32_t * CSystemRegisters : : _PROGRAM_COUNTER = nullptr ;
MIPS_DWORD * CSystemRegisters : : _GPR = nullptr ;
MIPS_DWORD * CSystemRegisters : : _FPR = nullptr ;
uint64_t * CSystemRegisters : : _CP0 = nullptr ;
MIPS_DWORD * CSystemRegisters : : _RegHI = nullptr ;
MIPS_DWORD * CSystemRegisters : : _RegLO = nullptr ;
float * * CSystemRegisters : : _FPR_S ;
double * * CSystemRegisters : : _FPR_D ;
uint32_t * CSystemRegisters : : _FPCR = nullptr ;
uint32_t * CSystemRegisters : : _LLBit = nullptr ;
int32_t * CSystemRegisters : : _RoundingModel = nullptr ;
2010-06-04 06:25:07 +00:00
2022-09-19 07:06:44 +00:00
CP0registers : : CP0registers ( uint64_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 ] ) ,
2022-09-19 12:06:36 +00:00
CONTEXT_REGISTER ( ( COP0Context & ) _CP0 [ 4 ] ) ,
2017-04-23 21:41:25 +00:00
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 ] ) ,
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER ( ( COP0Cause & ) _CP0 [ 13 ] ) ,
2017-04-23 21:41:25 +00:00
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 ] ) ,
2022-09-19 12:06:36 +00:00
XCONTEXT_REGISTER ( ( COP0XContext & ) _CP0 [ 20 ] ) ,
2017-04-23 21:41:25 +00:00
TAGLO_REGISTER ( _CP0 [ 28 ] ) ,
TAGHI_REGISTER ( _CP0 [ 29 ] ) ,
2023-03-14 01:44:10 +00:00
ERROREPC_REGISTER ( _CP0 [ 30 ] )
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 ) ) ;
2022-12-12 04:57:07 +00:00
m_FPCR [ 0 ] = 0xA00 ;
2022-10-16 22:36:22 +00:00
m_CP0Latch = 0 ;
2015-11-13 06:34:57 +00:00
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
}
2022-11-06 22:54:58 +00:00
uint64_t CRegisters : : Cop0_MF ( COP0Reg Reg )
2022-09-19 07:06:44 +00:00
{
2022-11-06 22:54:58 +00:00
if ( LogCP0reads ( ) & & Reg < = COP0Reg_31 )
2022-09-19 07:06:44 +00:00
{
LogMessage ( " %08X: R4300i read from %s (0x%08X) " , ( * _PROGRAM_COUNTER ) , CRegName : : Cop0 [ Reg ] , m_CP0 [ Reg ] ) ;
}
2022-11-06 22:54:58 +00:00
if ( Reg = = COP0Reg_Count | | Reg = = COP0Reg_Wired | | Reg = = COP0Reg_Random )
2022-09-19 07:06:44 +00:00
{
g_SystemTimer - > UpdateTimers ( ) ;
}
2022-11-06 22:54:58 +00:00
else if ( Reg = = COP0Reg_7 | | Reg = = COP0Reg_21 | | Reg = = COP0Reg_22 | | Reg = = COP0Reg_23 | | Reg = = COP0Reg_24 | | Reg = = COP0Reg_25 | | Reg = = COP0Reg_31 )
2022-10-16 22:36:22 +00:00
{
// Unused registers
return m_CP0Latch ;
}
2022-11-06 22:54:58 +00:00
return Reg < = COP0Reg_31 ? m_CP0 [ Reg ] : 0 ;
2022-09-19 07:06:44 +00:00
}
2022-11-06 22:54:58 +00:00
void CRegisters : : Cop0_MT ( COP0Reg Reg , uint64_t Value )
2022-09-19 07:06:44 +00:00
{
2022-11-06 22:54:58 +00:00
if ( LogCP0changes ( ) & & Reg < = COP0Reg_31 )
2022-09-19 07:06:44 +00:00
{
LogMessage ( " %08X: Writing 0x%I64U to %s register (originally: 0x%I64U) " , ( * _PROGRAM_COUNTER ) , Value , CRegName : : Cop0 [ Reg ] , m_CP0 [ Reg ] ) ;
2022-10-10 00:22:17 +00:00
if ( Reg = = 11 ) // Compare
2022-09-19 07:06:44 +00:00
{
2023-03-14 01:44:10 +00:00
LogMessage ( " %08X: Cause register changed from %08X to %08X " , ( * _PROGRAM_COUNTER ) , ( uint32_t ) CAUSE_REGISTER . Value , ( uint32_t ) ( g_Reg - > CAUSE_REGISTER . Value & ~ CAUSE_IP7 ) ) ;
2022-09-19 07:06:44 +00:00
}
}
2022-10-16 22:36:22 +00:00
m_CP0Latch = Value ;
2022-09-19 07:06:44 +00:00
switch ( Reg )
{
2022-11-06 22:54:58 +00:00
case COP0Reg_EPC :
case COP0Reg_WatchLo :
case COP0Reg_WatchHi :
case COP0Reg_TagLo :
case COP0Reg_TagHi :
case COP0Reg_ErrEPC :
case COP0Reg_31 :
2022-09-19 07:06:44 +00:00
m_CP0 [ Reg ] = Value ;
break ;
2022-11-14 10:26:21 +00:00
case COP0Reg_Index :
m_CP0 [ Reg ] = Value & 0x8000003F ;
break ;
case COP0Reg_Random :
// Ignore - Read only
break ;
case COP0Reg_EntryLo0 :
case COP0Reg_EntryLo1 :
m_CP0 [ Reg ] = Value & 0x3FFFFFFF ;
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_Context :
2022-10-16 22:36:22 +00:00
m_CP0 [ Reg ] = ( Value & 0xFFFFFFFFFF800000 ) | ( m_CP0 [ Reg ] & 0x7FFFF0 ) ;
break ;
2022-11-14 10:26:21 +00:00
case COP0Reg_PageMask :
m_CP0 [ Reg ] = Value & 0x1FFE000 ;
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_Wired :
2022-09-19 07:06:44 +00:00
g_SystemTimer - > UpdateTimers ( ) ;
2022-10-16 22:36:22 +00:00
m_CP0 [ Reg ] = Value & 0x3F ;
2022-09-19 07:06:44 +00:00
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_7 :
case COP0Reg_BadVAddr :
2022-11-14 10:26:21 +00:00
// Ignore - Read only
2022-09-19 07:06:44 +00:00
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_Count :
2022-09-19 07:06:44 +00:00
g_SystemTimer - > UpdateTimers ( ) ;
m_CP0 [ Reg ] = Value ;
g_SystemTimer - > UpdateCompareTimer ( ) ;
break ;
2022-11-14 10:26:21 +00:00
case COP0Reg_EntryHi :
m_CP0 [ Reg ] = Value & 0xC00000FFFFFFE0FF ;
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_Compare :
2022-09-19 07:06:44 +00:00
g_SystemTimer - > UpdateTimers ( ) ;
m_CP0 [ Reg ] = Value ;
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . PendingInterrupts & = ~ CAUSE_IP7 ;
2022-09-19 07:06:44 +00:00
g_SystemTimer - > UpdateCompareTimer ( ) ;
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_Status :
2022-10-16 22:36:22 +00:00
{
bool FRBitChanged = ( m_CP0 [ Reg ] & STATUS_FR ) ! = ( Value & STATUS_FR ) ;
m_CP0 [ Reg ] = Value & 0xFFF7FFFF ;
if ( FRBitChanged )
2022-09-19 07:06:44 +00:00
{
FixFpuLocations ( ) ;
}
CheckInterrupts ( ) ;
break ;
2022-10-16 22:36:22 +00:00
}
2022-11-06 22:54:58 +00:00
case COP0Reg_Cause :
2022-09-19 07:06:44 +00:00
m_CP0 [ Reg ] & = 0xFFFFCFF ;
if ( ( Value & 0x300 ) ! = 0 & & HaveDebugger ( ) )
{
g_Notify - > DisplayError ( " Set IP0 or IP1 " ) ;
}
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_PRId :
// Read only
2022-10-16 22:36:22 +00:00
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_Config :
2022-11-14 10:26:21 +00:00
m_CP0 [ Reg ] = ( Value & 0x0F00800F ) | ( m_CP0 [ Reg ] & 0xF0FF7FF0 ) ;
2022-10-16 22:36:22 +00:00
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_LLAddr :
2022-10-16 22:36:22 +00:00
m_CP0 [ Reg ] = ( Value & 0xFFFFFFFF ) | ( m_CP0 [ Reg ] & 0xFFFFFFFF00000000 ) ;
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_XContext :
2022-10-16 22:36:22 +00:00
m_CP0 [ Reg ] = ( Value & 0xFFFFFFFE00000000 ) | ( m_CP0 [ Reg ] & 0x00000001FFFFFFFF ) ;
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_21 :
case COP0Reg_22 :
case COP0Reg_23 :
case COP0Reg_24 :
case COP0Reg_25 :
// Unused
2022-10-16 22:36:22 +00:00
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_ParityError :
2022-10-16 22:36:22 +00:00
m_CP0 [ Reg ] = Value & 0xFF ;
break ;
2022-11-06 22:54:58 +00:00
case COP0Reg_CacheErr :
2022-10-16 22:36:22 +00:00
break ;
2022-09-19 07:06:44 +00:00
default :
if ( HaveDebugger ( ) )
{
g_Notify - > BreakPoint ( __FILE__ , __LINE__ ) ;
}
}
}
2023-01-02 09:19:19 +00:00
void CRegisters : : Cop1_CT ( uint32_t Reg , uint32_t Value )
{
if ( Reg = = 31 )
{
FPStatusReg & StatusReg = ( FPStatusReg & ) _FPCR [ 31 ] ;
StatusReg . Value = ( Value & 0x183FFFF ) ;
switch ( StatusReg . RoundingMode )
{
case 0 : * _RoundingModel = FE_TONEAREST ; break ;
case 1 : * _RoundingModel = FE_TOWARDZERO ; break ;
case 2 : * _RoundingModel = FE_UPWARD ; break ;
case 3 : * _RoundingModel = FE_DOWNWARD ; break ;
}
if ( ( ( StatusReg . Cause . Inexact & StatusReg . Enable . Inexact ) ! = 0 ) | |
( ( StatusReg . Cause . Underflow & StatusReg . Enable . Underflow ) ! = 0 ) | |
( ( StatusReg . Cause . Overflow & StatusReg . Enable . Overflow ) ! = 0 ) | |
( ( StatusReg . Cause . DivisionByZero & StatusReg . Enable . DivisionByZero ) ! = 0 ) | |
( ( StatusReg . Cause . InvalidOperation & StatusReg . Enable . InvalidOperation ) ! = 0 ) | |
( StatusReg . Cause . UnimplementedOperation ! = 0 ) )
{
DoFloatingPointException ( m_System - > m_PipelineStage = = PIPELINE_STAGE_JUMP ) ;
m_System - > m_PipelineStage = PIPELINE_STAGE_JUMP ;
m_System - > m_JumpToLocation = ( * _PROGRAM_COUNTER ) ;
}
}
}
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
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . PendingInterrupts | = CAUSE_IP2 ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . PendingInterrupts & = ~ CAUSE_IP2 ;
2015-11-08 20:45:41 +00:00
}
2016-02-10 00:59:46 +00:00
MI_INTR_REG = mi_intr_reg ;
2022-09-19 07:06:44 +00:00
status_register = ( uint32_t ) 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 ;
}
2023-03-14 01:44:10 +00:00
if ( ( status_register & CAUSE_REGISTER . Value & 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
}
2022-09-19 12:06:36 +00:00
void CRegisters : : DoAddressError ( bool DelaySlot , uint64_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 )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_RADE ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_WADE ;
2015-11-08 20:45:41 +00:00
}
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2015-11-08 20:45:41 +00:00
BAD_VADDR_REGISTER = BadVaddr ;
2022-09-19 12:06:36 +00:00
CONTEXT_REGISTER . BadVPN2 = BadVaddr > > 13 ;
XCONTEXT_REGISTER . BadVPN2 = BadVaddr > > 13 ;
2022-10-03 00:59:21 +00:00
XCONTEXT_REGISTER . R = BadVaddr > > 61 ;
2022-09-19 12:06:36 +00:00
2015-11-08 20:45:41 +00:00
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-09-19 12:06:36 +00:00
EPC_REGISTER = ( int32_t ) ( m_PROGRAM_COUNTER - 4 ) ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-09-19 12:06:36 +00:00
EPC_REGISTER = ( int32_t ) m_PROGRAM_COUNTER ;
2015-11-08 20:45:41 +00:00
}
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
}
}
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_BREAK ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2015-11-08 20:45:41 +00:00
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2015-11-08 20:45:41 +00:00
}
STATUS_REGISTER | = STATUS_EXL ;
m_PROGRAM_COUNTER = 0x80000180 ;
2010-06-04 06:25:07 +00:00
}
2023-01-02 09:19:19 +00:00
void CRegisters : : DoFloatingPointException ( bool DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_FPE ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2023-01-02 09:19:19 +00:00
if ( DelaySlot )
{
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2023-01-02 09:19:19 +00:00
}
else
{
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2023-01-02 09:19:19 +00:00
}
STATUS_REGISTER | = STATUS_EXL ;
m_PROGRAM_COUNTER = 0x80000180 ;
}
2019-12-16 20:15:26 +00:00
void CRegisters : : DoTrapException ( bool DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_TRAP ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2019-12-16 20:15:26 +00:00
if ( DelaySlot )
{
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2019-12-16 20:15:26 +00:00
}
else
{
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2019-12-16 20:15:26 +00:00
}
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
}
}
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_CPU ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = Coprocessor ;
2015-11-08 20:45:41 +00:00
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2015-11-08 20:45:41 +00:00
}
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
}
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_INT ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2015-11-08 20:45:41 +00:00
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2015-11-08 20:45:41 +00:00
}
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 )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_II ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2022-09-19 02:42:08 +00:00
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2022-09-19 02:42:08 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2022-09-19 02:42:08 +00:00
}
m_PROGRAM_COUNTER = 0x80000180 ;
STATUS_REGISTER | = STATUS_EXL ;
}
2022-09-05 07:05:13 +00:00
void CRegisters : : DoOverflowException ( bool DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_OV ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2022-09-05 07:05:13 +00:00
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2022-09-05 07:05:13 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2022-09-05 07:05:13 +00:00
}
m_PROGRAM_COUNTER = 0x80000180 ;
STATUS_REGISTER | = STATUS_EXL ;
}
2022-09-19 12:06:36 +00:00
void CRegisters : : DoTLBReadMiss ( bool DelaySlot , uint64_t BadVaddr )
2010-06-04 06:25:07 +00:00
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_RMISS ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2015-11-08 20:45:41 +00:00
BAD_VADDR_REGISTER = BadVaddr ;
2022-09-19 12:06:36 +00:00
CONTEXT_REGISTER . BadVPN2 = BadVaddr > > 13 ;
2015-11-08 20:45:41 +00:00
ENTRYHI_REGISTER = ( BadVaddr & 0xFFFFE000 ) ;
if ( ( STATUS_REGISTER & STATUS_EXL ) = = 0 )
{
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2015-11-08 20:45:41 +00:00
}
2022-09-19 12:06:36 +00:00
if ( g_TLB - > AddressDefined ( ( uint32_t ) BadVaddr ) )
2015-11-08 20:45:41 +00:00
{
m_PROGRAM_COUNTER = 0x80000180 ;
}
else
{
m_PROGRAM_COUNTER = 0x80000000 ;
}
2020-03-04 00:03:18 +00:00
STATUS_REGISTER | = STATUS_EXL ;
}
else
{
if ( HaveDebugger ( ) )
{
2022-09-19 12:06:36 +00:00
g_Notify - > DisplayError ( stdstr_f ( " TLBMiss - EXL set \n BadVaddr = %X \n Address defined: %s " , ( uint32_t ) BadVaddr , g_TLB - > AddressDefined ( ( uint32_t ) BadVaddr ) ? " true " : " false " ) . c_str ( ) ) ;
2020-03-04 00:03:18 +00:00
}
m_PROGRAM_COUNTER = 0x80000180 ;
}
}
2022-09-19 12:06:36 +00:00
void CRegisters : : DoTLBWriteMiss ( bool DelaySlot , uint64_t BadVaddr )
2020-03-04 00:03:18 +00:00
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_WMISS ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2020-03-04 00:03:18 +00:00
BAD_VADDR_REGISTER = BadVaddr ;
2022-09-19 12:06:36 +00:00
CONTEXT_REGISTER . BadVPN2 = BadVaddr > > 13 ;
2020-03-04 00:03:18 +00:00
ENTRYHI_REGISTER = ( BadVaddr & 0xFFFFE000 ) ;
if ( ( STATUS_REGISTER & STATUS_EXL ) = = 0 )
{
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2020-03-04 00:03:18 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER ) ;
2020-03-04 00:03:18 +00:00
}
2022-09-19 12:06:36 +00:00
if ( g_TLB - > AddressDefined ( ( uint32_t ) BadVaddr ) )
2020-03-04 00:03:18 +00:00
{
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
{
2022-09-19 12:06:36 +00:00
g_Notify - > DisplayError ( stdstr_f ( " TLBMiss - EXL set \n BadVaddr = %X \n Address defined: %s " , ( uint32_t ) BadVaddr , g_TLB - > AddressDefined ( ( uint32_t ) 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
}
}
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . ExceptionCode = EXC_SYSCALL ;
2023-03-20 01:39:06 +00:00
CAUSE_REGISTER . CoprocessorUnitNumber = 0 ;
2015-11-08 20:45:41 +00:00
if ( DelaySlot )
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 1 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( ( int32_t ) m_PROGRAM_COUNTER - 4 ) ;
2015-11-08 20:45:41 +00:00
}
else
{
2023-03-14 01:44:10 +00:00
CAUSE_REGISTER . BranchDelay = 0 ;
2022-10-02 23:04:13 +00:00
EPC_REGISTER = ( int64_t ) ( int32_t ) m_PROGRAM_COUNTER ;
2015-11-08 20:45:41 +00:00
}
STATUS_REGISTER | = STATUS_EXL ;
m_PROGRAM_COUNTER = 0x80000180 ;
2017-08-18 05:08:22 +00:00
}