summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/psx/psx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/psx/psx.cpp')
-rw-r--r--src/devices/cpu/psx/psx.cpp1530
1 files changed, 780 insertions, 750 deletions
diff --git a/src/devices/cpu/psx/psx.cpp b/src/devices/cpu/psx/psx.cpp
index 6ce8ed7a7b1..36d7c1742f4 100644
--- a/src/devices/cpu/psx/psx.cpp
+++ b/src/devices/cpu/psx/psx.cpp
@@ -29,7 +29,7 @@
*
* Known limitations of the emulation:
*
- * Only read & write break points are emulated, trace and program counter breakpoints are not.
+ * Program counter, read data & write data break points are emulated, trace break points are not.
*
* Load/Store timings are based on load scheduling turned off & no write cache. This affects when
* bus error exceptions occur and also when the read & write handlers are called. A scheduled
@@ -61,7 +61,7 @@
*
* Wait states are not emulated.
*
- * Bus errors caused by instruction fetches are not supported.
+ * Bus errors caused by instruction burst fetches are not supported.
*
*/
@@ -105,15 +105,22 @@
#define CP0_EPC ( 14 )
#define CP0_PRID ( 15 )
-#define DCIC_STATUS ( 0x3f )
#define DCIC_DB ( 1L << 0 )
+#define DCIC_PC ( 1L << 1 )
#define DCIC_DA ( 1L << 2 )
#define DCIC_R ( 1L << 3 )
#define DCIC_W ( 1L << 4 )
+#define DCIC_T ( 1L << 5 ) // not emulated
+// unknown ( 1L << 12 )
+// unknown ( 1L << 13 )
+// unknown ( 1L << 14 )
+// unknown ( 1L << 15 )
#define DCIC_DE ( 1L << 23 )
+#define DCIC_PCE ( 1L << 24 )
#define DCIC_DAE ( 1L << 25 )
#define DCIC_DR ( 1L << 26 )
#define DCIC_DW ( 1L << 27 )
+#define DCIC_TE ( 1L << 28 ) // not emulated
#define DCIC_KD ( 1L << 29 )
#define DCIC_UD ( 1L << 30 )
#define DCIC_TR ( 1L << 31 )
@@ -1445,12 +1452,6 @@ void psxcpu_device::update_cop0( int reg )
execute_unstoppable_instructions( 1 );
exception( EXC_INT );
}
- else if( reg == CP0_SR &&
- m_delayr != PSXCPU_DELAYR_PC &&
- ( m_pc & m_bad_word_address_mask ) != 0 )
- {
- load_bad_address( m_pc );
- }
}
void psxcpu_device::commit_delayed_load()
@@ -1482,19 +1483,13 @@ void psxcpu_device::fetch_next_op()
}
}
-int psxcpu_device::advance_pc()
+void psxcpu_device::advance_pc()
{
if( m_delayr == PSXCPU_DELAYR_PC )
{
m_pc = m_delayv;
m_delayr = 0;
m_delayv = 0;
-
- if( ( m_pc & m_bad_word_address_mask ) != 0 )
- {
- load_bad_address( m_pc );
- return 0;
- }
}
else if( m_delayr == PSXCPU_DELAYR_NOTPC )
{
@@ -1507,8 +1502,6 @@ int psxcpu_device::advance_pc()
commit_delayed_load();
m_pc += 4;
}
-
- return 1;
}
void psxcpu_device::load( uint32_t reg, uint32_t value )
@@ -1648,8 +1641,11 @@ void psxcpu_device::store_bus_error_exception()
if( execute_unstoppable_instructions( 1 ) )
{
- if( !advance_pc() )
+ advance_pc();
+
+ if( ( m_pc & m_bad_word_address_mask ) != 0 )
{
+ load_bad_address( m_pc );
return;
}
@@ -1677,13 +1673,13 @@ int psxcpu_device::data_address_breakpoint( int dcic_rw, int dcic_status, uint32
if( address < 0x1f000000 || address > 0x1fffffff )
{
if( ( m_cp0r[ CP0_DCIC ] & DCIC_DE ) != 0 &&
- ( ( ( m_cp0r[ CP0_DCIC ] & DCIC_KD ) != 0 && ( m_cp0r[ CP0_SR ] & SR_KUC ) == 0 ) ||
- ( ( m_cp0r[ CP0_DCIC ] & DCIC_UD ) != 0 && ( m_cp0r[ CP0_SR ] & SR_KUC ) != 0 ) ) )
+ ( m_cp0r[ CP0_DCIC ] & dcic_rw ) == dcic_rw &&
+ ( ( ( m_cp0r[ CP0_DCIC ] & DCIC_KD ) != 0 && ( m_pc & 0x80000000 ) != 0 ) ||
+ ( ( m_cp0r[ CP0_DCIC ] & DCIC_UD ) != 0 && ( m_pc & 0x80000000 ) == 0 ) ) )
{
- if( ( m_cp0r[ CP0_DCIC ] & dcic_rw ) == dcic_rw &&
- ( address & m_cp0r[ CP0_BDAM ] ) == ( m_cp0r[ CP0_BDA ] & m_cp0r[ CP0_BDAM ] ) )
+ if( ( address & m_cp0r[ CP0_BDAM ] ) == ( m_cp0r[ CP0_BDA ] & m_cp0r[ CP0_BDAM ] ) )
{
- m_cp0r[ CP0_DCIC ] = ( m_cp0r[ CP0_DCIC ] & ~DCIC_STATUS ) | dcic_status;
+ m_cp0r[ CP0_DCIC ] |= dcic_status;
if( ( m_cp0r[ CP0_DCIC ] & DCIC_TR ) != 0 )
{
@@ -1696,6 +1692,27 @@ int psxcpu_device::data_address_breakpoint( int dcic_rw, int dcic_status, uint32
return 0;
}
+int psxcpu_device::program_counter_breakpoint()
+{
+ if( ( m_cp0r[ CP0_DCIC ] & DCIC_DE ) != 0 &&
+ ( m_cp0r[ CP0_DCIC ] & DCIC_PCE ) != 0 &&
+ ( ( ( m_cp0r[ CP0_DCIC ] & DCIC_KD ) != 0 && ( m_pc & 0x80000000 ) != 0 ) ||
+ ( ( m_cp0r[ CP0_DCIC ] & DCIC_UD ) != 0 && ( m_pc & 0x80000000 ) == 0 ) ) )
+ {
+ if( ( m_pc & m_cp0r[ CP0_BPCM ] ) == ( m_cp0r[ CP0_BPC ] & m_cp0r[ CP0_BPCM ] ) )
+ {
+ m_cp0r[ CP0_DCIC ] |= DCIC_PC | DCIC_DB;
+
+ if( ( m_cp0r[ CP0_DCIC ] & DCIC_TR ) != 0 )
+ {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
int psxcpu_device::load_data_address_breakpoint( uint32_t address )
{
return data_address_breakpoint( DCIC_DR | DCIC_DAE, DCIC_DB | DCIC_DA | DCIC_R, address );
@@ -2295,450 +2312,337 @@ void psxcpu_device::execute_run()
if( LOG_BIOSCALL ) log_bioscall();
debugger_instruction_hook( this, m_pc );
- m_op = m_direct->read_dword( m_pc );
+ int breakpoint = program_counter_breakpoint();
- if( m_berr )
+ if( ( m_pc & m_bad_word_address_mask ) != 0 )
{
- fetch_bus_error_exception();
+ load_bad_address( m_pc );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
}
else
{
- switch( INS_OP( m_op ) )
+ m_op = m_direct->read_dword(m_pc);
+
+ if( m_berr )
{
- case OP_SPECIAL:
- switch( INS_FUNCT( m_op ) )
+ fetch_bus_error_exception();
+ }
+ else
+ {
+ switch( INS_OP( m_op ) )
{
- case FUNCT_SLL:
- load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << INS_SHAMT( m_op ) );
- break;
+ case OP_SPECIAL:
+ switch( INS_FUNCT( m_op ) )
+ {
+ case FUNCT_SLL:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << INS_SHAMT( m_op ) );
+ break;
- case FUNCT_SRL:
- load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
- break;
+ case FUNCT_SRL:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
+ break;
- case FUNCT_SRA:
- load( INS_RD( m_op ), (int32_t)m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
- break;
+ case FUNCT_SRA:
+ load( INS_RD( m_op ), (int32_t)m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
+ break;
- case FUNCT_SLLV:
- load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << ( m_r[ INS_RS( m_op ) ] & 31 ) );
- break;
+ case FUNCT_SLLV:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << ( m_r[ INS_RS( m_op ) ] & 31 ) );
+ break;
- case FUNCT_SRLV:
- load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
- break;
+ case FUNCT_SRLV:
+ load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
+ break;
- case FUNCT_SRAV:
- load( INS_RD( m_op ), (int32_t)m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
- break;
+ case FUNCT_SRAV:
+ load( INS_RD( m_op ), (int32_t)m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
+ break;
- case FUNCT_JR:
- branch( m_r[ INS_RS( m_op ) ] );
- break;
+ case FUNCT_JR:
+ branch( m_r[ INS_RS( m_op ) ] );
+ break;
- case FUNCT_JALR:
- branch( m_r[ INS_RS( m_op ) ] );
- if( INS_RD( m_op ) != 0 )
- {
- m_r[ INS_RD( m_op ) ] = m_pc + 4;
- }
- break;
+ case FUNCT_JALR:
+ branch( m_r[ INS_RS( m_op ) ] );
+ if( INS_RD( m_op ) != 0 )
+ {
+ m_r[ INS_RD( m_op ) ] = m_pc + 4;
+ }
+ break;
- case FUNCT_SYSCALL:
- if( LOG_BIOSCALL ) log_syscall();
- exception( EXC_SYS );
- break;
+ case FUNCT_SYSCALL:
+ if( LOG_BIOSCALL ) log_syscall();
+ exception( EXC_SYS );
+ break;
- case FUNCT_BREAK:
- exception( EXC_BP );
- break;
+ case FUNCT_BREAK:
+ exception( EXC_BP );
+ break;
- case FUNCT_MFHI:
- load( INS_RD( m_op ), get_hi() );
- break;
+ case FUNCT_MFHI:
+ load( INS_RD( m_op ), get_hi() );
+ break;
- case FUNCT_MTHI:
- funct_mthi();
- advance_pc();
- break;
+ case FUNCT_MTHI:
+ funct_mthi();
+ advance_pc();
+ break;
- case FUNCT_MFLO:
- load( INS_RD( m_op ), get_lo() );
- break;
+ case FUNCT_MFLO:
+ load( INS_RD( m_op ), get_lo() );
+ break;
- case FUNCT_MTLO:
- funct_mtlo();
- advance_pc();
- break;
+ case FUNCT_MTLO:
+ funct_mtlo();
+ advance_pc();
+ break;
- case FUNCT_MULT:
- funct_mult();
- advance_pc();
- break;
+ case FUNCT_MULT:
+ funct_mult();
+ advance_pc();
+ break;
- case FUNCT_MULTU:
- funct_multu();
- advance_pc();
- break;
+ case FUNCT_MULTU:
+ funct_multu();
+ advance_pc();
+ break;
- case FUNCT_DIV:
- funct_div();
- advance_pc();
- break;
+ case FUNCT_DIV:
+ funct_div();
+ advance_pc();
+ break;
- case FUNCT_DIVU:
- funct_divu();
- advance_pc();
- break;
+ case FUNCT_DIVU:
+ funct_divu();
+ advance_pc();
+ break;
- case FUNCT_ADD:
- {
- uint32_t result = m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ];
- if( (int32_t)( ~( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
- {
- exception( EXC_OVF );
- }
- else
+ case FUNCT_ADD:
{
- load( INS_RD( m_op ), result );
+ uint32_t result = m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ];
+ if( (int32_t)( ~( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
+ {
+ exception( EXC_OVF );
+ }
+ else
+ {
+ load( INS_RD( m_op ), result );
+ }
}
- }
- break;
+ break;
- case FUNCT_ADDU:
- load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ] );
- break;
+ case FUNCT_ADDU:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ] );
+ break;
- case FUNCT_SUB:
- {
- uint32_t result = m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ];
- if( (int32_t)( ( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
- {
- exception( EXC_OVF );
- }
- else
+ case FUNCT_SUB:
{
- load( INS_RD( m_op ), result );
+ uint32_t result = m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ];
+ if( (int32_t)( ( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
+ {
+ exception( EXC_OVF );
+ }
+ else
+ {
+ load( INS_RD( m_op ), result );
+ }
}
- }
- break;
-
- case FUNCT_SUBU:
- load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ] );
- break;
-
- case FUNCT_AND:
- load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] & m_r[ INS_RT( m_op ) ] );
- break;
+ break;
- case FUNCT_OR:
- load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] );
- break;
+ case FUNCT_SUBU:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ] );
+ break;
- case FUNCT_XOR:
- load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] );
- break;
+ case FUNCT_AND:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] & m_r[ INS_RT( m_op ) ] );
+ break;
- case FUNCT_NOR:
- load( INS_RD( m_op ), ~( m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] ) );
- break;
+ case FUNCT_OR:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] );
+ break;
- case FUNCT_SLT:
- load( INS_RD( m_op ), (int32_t)m_r[ INS_RS( m_op ) ] < (int32_t)m_r[ INS_RT( m_op ) ] );
- break;
+ case FUNCT_XOR:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] );
+ break;
- case FUNCT_SLTU:
- load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] < m_r[ INS_RT( m_op ) ] );
- break;
+ case FUNCT_NOR:
+ load( INS_RD( m_op ), ~( m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] ) );
+ break;
- default:
- exception( EXC_RI );
- break;
- }
- break;
+ case FUNCT_SLT:
+ load( INS_RD( m_op ), (int32_t)m_r[ INS_RS( m_op ) ] < (int32_t)m_r[ INS_RT( m_op ) ] );
+ break;
- case OP_REGIMM:
- switch( INS_RT_REGIMM( m_op ) )
- {
- case RT_BLTZ:
- conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] < 0 );
+ case FUNCT_SLTU:
+ load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] < m_r[ INS_RT( m_op ) ] );
+ break;
- if( INS_RT( m_op ) == RT_BLTZAL )
- {
- m_r[ 31 ] = m_pc + 4;
+ default:
+ exception( EXC_RI );
+ break;
}
break;
- case RT_BGEZ:
- conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] >= 0 );
-
- if( INS_RT( m_op ) == RT_BGEZAL )
+ case OP_REGIMM:
+ switch( INS_RT_REGIMM( m_op ) )
{
- m_r[ 31 ] = m_pc + 4;
- }
- break;
- }
- break;
+ case RT_BLTZ:
+ conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] < 0 );
- case OP_J:
- unconditional_branch();
- break;
-
- case OP_JAL:
- unconditional_branch();
- m_r[ 31 ] = m_pc + 4;
- break;
-
- case OP_BEQ:
- conditional_branch( m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
- break;
-
- case OP_BNE:
- conditional_branch( m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
- break;
-
- case OP_BLEZ:
- conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] < 0 || m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
- break;
+ if( INS_RT( m_op ) == RT_BLTZAL )
+ {
+ m_r[ 31 ] = m_pc + 4;
+ }
+ break;
- case OP_BGTZ:
- conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] >= 0 && m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
- break;
+ case RT_BGEZ:
+ conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] >= 0 );
- case OP_ADDI:
- {
- uint32_t immediate = PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- uint32_t result = m_r[ INS_RS( m_op ) ] + immediate;
- if( (int32_t)( ~( m_r[ INS_RS( m_op ) ] ^ immediate ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
- {
- exception( EXC_OVF );
- }
- else
- {
- load( INS_RT( m_op ), result );
+ if( INS_RT( m_op ) == RT_BGEZAL )
+ {
+ m_r[ 31 ] = m_pc + 4;
+ }
+ break;
}
- }
- break;
-
- case OP_ADDIU:
- load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
- break;
+ break;
- case OP_SLTI:
- load( INS_RT( m_op ), (int32_t)m_r[ INS_RS( m_op ) ] < PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
- break;
+ case OP_J:
+ unconditional_branch();
+ break;
- case OP_SLTIU:
- load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] < (uint32_t)PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
- break;
+ case OP_JAL:
+ unconditional_branch();
+ m_r[ 31 ] = m_pc + 4;
+ break;
- case OP_ANDI:
- load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] & INS_IMMEDIATE( m_op ) );
- break;
+ case OP_BEQ:
+ conditional_branch( m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
+ break;
- case OP_ORI:
- load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] | INS_IMMEDIATE( m_op ) );
- break;
+ case OP_BNE:
+ conditional_branch( m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
+ break;
- case OP_XORI:
- load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] ^ INS_IMMEDIATE( m_op ) );
- break;
+ case OP_BLEZ:
+ conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] < 0 || m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
+ break;
- case OP_LUI:
- load( INS_RT( m_op ), INS_IMMEDIATE( m_op ) << 16 );
- break;
+ case OP_BGTZ:
+ conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] >= 0 && m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
+ break;
- case OP_COP0:
- switch( INS_RS( m_op ) )
- {
- case RS_MFC:
+ case OP_ADDI:
{
- int reg = INS_RD( m_op );
-
- if( reg == CP0_INDEX ||
- reg == CP0_RANDOM ||
- reg == CP0_ENTRYLO ||
- reg == CP0_CONTEXT ||
- reg == CP0_ENTRYHI )
+ uint32_t immediate = PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ uint32_t result = m_r[ INS_RS( m_op ) ] + immediate;
+ if( (int32_t)( ~( m_r[ INS_RS( m_op ) ] ^ immediate ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
{
- exception( EXC_RI );
- }
- else if( reg < 16 )
- {
- if( cop0_usable() )
- {
- delayed_load( INS_RT( m_op ), m_cp0r[ reg ] );
- }
+ exception( EXC_OVF );
}
else
{
- advance_pc();
+ load( INS_RT( m_op ), result );
}
}
break;
- case RS_CFC:
- exception( EXC_RI );
+ case OP_ADDIU:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
break;
- case RS_MTC:
- {
- int reg = INS_RD( m_op );
+ case OP_SLTI:
+ load( INS_RT( m_op ), (int32_t)m_r[ INS_RS( m_op ) ] < PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
+ break;
- if( reg == CP0_INDEX ||
- reg == CP0_RANDOM ||
- reg == CP0_ENTRYLO ||
- reg == CP0_CONTEXT ||
- reg == CP0_ENTRYHI )
- {
- exception( EXC_RI );
- }
- else if( reg < 16 )
- {
- if( cop0_usable() )
- {
- uint32_t data = ( m_cp0r[ reg ] & ~mtc0_writemask[ reg ] ) |
- ( m_r[ INS_RT( m_op ) ] & mtc0_writemask[ reg ] );
- advance_pc();
+ case OP_SLTIU:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] < (uint32_t)PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
+ break;
- m_cp0r[ reg ] = data;
- update_cop0( reg );
- }
- }
- else
- {
- advance_pc();
- }
- }
+ case OP_ANDI:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] & INS_IMMEDIATE( m_op ) );
break;
- case RS_CTC:
- exception( EXC_RI );
+ case OP_ORI:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] | INS_IMMEDIATE( m_op ) );
break;
- case RS_BC:
- case RS_BC_ALT:
- switch( INS_BC( m_op ) )
- {
- case BC_BCF:
- bc( 0, SR_CU0, 0 );
- break;
+ case OP_XORI:
+ load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] ^ INS_IMMEDIATE( m_op ) );
+ break;
- case BC_BCT:
- bc( 0, SR_CU0, 1 );
- break;
- }
+ case OP_LUI:
+ load( INS_RT( m_op ), INS_IMMEDIATE( m_op ) << 16 );
break;
- default:
- switch( INS_CO( m_op ) )
+ case OP_COP0:
+ switch( INS_RS( m_op ) )
{
- case 1:
- switch( INS_CF( m_op ) )
+ case RS_MFC:
{
- case CF_TLBR:
- case CF_TLBWI:
- case CF_TLBWR:
- case CF_TLBP:
- exception( EXC_RI );
- break;
+ int reg = INS_RD( m_op );
- case CF_RFE:
- if( cop0_usable() )
+ if( reg == CP0_INDEX ||
+ reg == CP0_RANDOM ||
+ reg == CP0_ENTRYLO ||
+ reg == CP0_CONTEXT ||
+ reg == CP0_ENTRYHI )
+ {
+ exception( EXC_RI );
+ }
+ else if( reg < 16 )
+ {
+ if( cop0_usable() )
+ {
+ delayed_load( INS_RT( m_op ), m_cp0r[ reg ] );
+ }
+ }
+ else
{
advance_pc();
- m_cp0r[ CP0_SR ] = ( m_cp0r[ CP0_SR ] & ~0xf ) | ( ( m_cp0r[ CP0_SR ] >> 2 ) & 0xf );
- update_cop0( CP0_SR );
}
- break;
-
- default:
- advance_pc();
- break;
}
break;
- default:
- advance_pc();
- break;
- }
- break;
- }
- break;
-
- case OP_COP1:
- if( ( m_cp0r[ CP0_SR ] & SR_CU1 ) == 0 )
- {
- exception( EXC_CPU );
- }
- else
- {
- switch( INS_RS( m_op ) )
- {
- case RS_MFC:
- delayed_load( INS_RT( m_op ), getcp1dr( INS_RD( m_op ) ) );
- break;
-
case RS_CFC:
- delayed_load( INS_RT( m_op ), getcp1cr( INS_RD( m_op ) ) );
+ exception( EXC_RI );
break;
case RS_MTC:
- setcp1dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
- advance_pc();
- break;
-
- case RS_CTC:
- setcp1cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
- advance_pc();
- break;
-
- case RS_BC:
- case RS_BC_ALT:
- switch( INS_BC( m_op ) )
{
- case BC_BCF:
- bc( 1, SR_CU1, 0 );
- break;
-
- case BC_BCT:
- bc( 1, SR_CU1, 1 );
- break;
- }
- break;
+ int reg = INS_RD( m_op );
- default:
- advance_pc();
- break;
- }
- }
- break;
-
- case OP_COP2:
- if( ( m_cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
- {
- exception( EXC_CPU );
- }
- else
- {
- switch( INS_RS( m_op ) )
- {
- case RS_MFC:
- delayed_load( INS_RT( m_op ), m_gte.getcp2dr( m_pc, INS_RD( m_op ) ) );
- break;
-
- case RS_CFC:
- delayed_load( INS_RT( m_op ), m_gte.getcp2cr( m_pc, INS_RD( m_op ) ) );
- break;
+ if( reg == CP0_INDEX ||
+ reg == CP0_RANDOM ||
+ reg == CP0_ENTRYLO ||
+ reg == CP0_CONTEXT ||
+ reg == CP0_ENTRYHI )
+ {
+ exception( EXC_RI );
+ }
+ else if( reg < 16 )
+ {
+ if( cop0_usable() )
+ {
+ uint32_t data = ( m_cp0r[ reg ] & ~mtc0_writemask[ reg ] ) |
+ ( m_r[ INS_RT( m_op ) ] & mtc0_writemask[ reg ] );
+ advance_pc();
- case RS_MTC:
- m_gte.setcp2dr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
- advance_pc();
+ m_cp0r[ reg ] = data;
+ update_cop0( reg );
+ }
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
break;
case RS_CTC:
- m_gte.setcp2cr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
- advance_pc();
+ exception( EXC_RI );
break;
case RS_BC:
@@ -2746,11 +2650,11 @@ void psxcpu_device::execute_run()
switch( INS_BC( m_op ) )
{
case BC_BCF:
- bc( 2, SR_CU2, 0 );
+ bc( 0, SR_CU0, 0 );
break;
case BC_BCT:
- bc( 2, SR_CU2, 1 );
+ bc( 0, SR_CU0, 1 );
break;
}
break;
@@ -2759,12 +2663,28 @@ void psxcpu_device::execute_run()
switch( INS_CO( m_op ) )
{
case 1:
- if( !m_gte.docop2( m_pc, INS_COFUN( m_op ) ) )
+ switch( INS_CF( m_op ) )
{
- stop();
- }
+ case CF_TLBR:
+ case CF_TLBWI:
+ case CF_TLBWR:
+ case CF_TLBP:
+ exception( EXC_RI );
+ break;
+
+ case CF_RFE:
+ if( cop0_usable() )
+ {
+ advance_pc();
+ m_cp0r[ CP0_SR ] = ( m_cp0r[ CP0_SR ] & ~0xf ) | ( ( m_cp0r[ CP0_SR ] >> 2 ) & 0xf );
+ update_cop0( CP0_SR );
+ }
+ break;
- advance_pc();
+ default:
+ advance_pc();
+ break;
+ }
break;
default:
@@ -2773,524 +2693,634 @@ void psxcpu_device::execute_run()
}
break;
}
- }
- break;
+ break;
- case OP_COP3:
- if( ( m_cp0r[ CP0_SR ] & SR_CU3 ) == 0 )
- {
- exception( EXC_CPU );
- }
- else
- {
- switch( INS_RS( m_op ) )
+ case OP_COP1:
+ if( ( m_cp0r[ CP0_SR ] & SR_CU1 ) == 0 )
{
- case RS_MFC:
- delayed_load( INS_RT( m_op ), getcp3dr( INS_RD( m_op ) ) );
- break;
+ exception( EXC_CPU );
+ }
+ else
+ {
+ switch( INS_RS( m_op ) )
+ {
+ case RS_MFC:
+ delayed_load( INS_RT( m_op ), getcp1dr( INS_RD( m_op ) ) );
+ break;
- case RS_CFC:
- delayed_load( INS_RT( m_op ), getcp3cr( INS_RD( m_op ) ) );
- break;
+ case RS_CFC:
+ delayed_load( INS_RT( m_op ), getcp1cr( INS_RD( m_op ) ) );
+ break;
- case RS_MTC:
- setcp3dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
- advance_pc();
- break;
+ case RS_MTC:
+ setcp1dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
- case RS_CTC:
- setcp3cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
- advance_pc();
- break;
+ case RS_CTC:
+ setcp1cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
- case RS_BC:
- case RS_BC_ALT:
- switch( INS_BC( m_op ) )
- {
- case BC_BCF:
- bc( 3, SR_CU3, 0 );
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( m_op ) )
+ {
+ case BC_BCF:
+ bc( 1, SR_CU1, 0 );
+ break;
+
+ case BC_BCT:
+ bc( 1, SR_CU1, 1 );
+ break;
+ }
break;
- case BC_BCT:
- bc( 3, SR_CU3, 1 );
+ default:
+ advance_pc();
break;
}
- break;
-
- default:
- advance_pc();
- break;
}
- }
- break;
-
- case OP_LB:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = load_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_byte_address_mask ) != 0 )
+ case OP_COP2:
+ if( ( m_cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
{
- load_bad_address( address );
- }
- else if( breakpoint )
- {
- breakpoint_exception();
+ exception( EXC_CPU );
}
else
{
- uint32_t data = PSXCPU_BYTE_EXTEND( readbyte( address ) );
-
- if( m_berr )
+ switch( INS_RS( m_op ) )
{
- load_bus_error_exception();
- }
- else
- {
- delayed_load( INS_RT( m_op ), data );
- }
- }
- }
- break;
+ case RS_MFC:
+ delayed_load( INS_RT( m_op ), m_gte.getcp2dr( m_pc, INS_RD( m_op ) ) );
+ break;
- case OP_LH:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = load_data_address_breakpoint( address );
+ case RS_CFC:
+ delayed_load( INS_RT( m_op ), m_gte.getcp2cr( m_pc, INS_RD( m_op ) ) );
+ break;
- if( ( address & m_bad_half_address_mask ) != 0 )
- {
- load_bad_address( address );
- }
- else if( breakpoint )
- {
- breakpoint_exception();
- }
- else
- {
- uint32_t data = PSXCPU_WORD_EXTEND( readhalf( address ) );
+ case RS_MTC:
+ m_gte.setcp2dr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
- if( m_berr )
- {
- load_bus_error_exception();
- }
- else
- {
- delayed_load( INS_RT( m_op ), data );
- }
- }
- }
- break;
+ case RS_CTC:
+ m_gte.setcp2cr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
- case OP_LWL:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int load_type = address & 3;
- int breakpoint;
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( m_op ) )
+ {
+ case BC_BCF:
+ bc( 2, SR_CU2, 0 );
+ break;
- address &= ~3;
- breakpoint = load_data_address_breakpoint( address );
+ case BC_BCT:
+ bc( 2, SR_CU2, 1 );
+ break;
+ }
+ break;
- if( ( address & m_bad_byte_address_mask ) != 0 )
- {
- load_bad_address( address );
+ default:
+ switch( INS_CO( m_op ) )
+ {
+ case 1:
+ if( !m_gte.docop2( m_pc, INS_COFUN( m_op ) ) )
+ {
+ stop();
+ }
+
+ advance_pc();
+ break;
+
+ default:
+ advance_pc();
+ break;
+ }
+ break;
+ }
}
- else if( breakpoint )
+ break;
+
+ case OP_COP3:
+ if( ( m_cp0r[ CP0_SR ] & SR_CU3 ) == 0 )
{
- breakpoint_exception();
+ exception( EXC_CPU );
}
else
{
- uint32_t data = get_register_from_pipeline( INS_RT( m_op ) );
-
- switch( load_type )
+ switch( INS_RS( m_op ) )
{
- case 0:
- data = ( data & 0x00ffffff ) | ( readword_masked( address, 0x000000ff ) << 24 );
+ case RS_MFC:
+ delayed_load( INS_RT( m_op ), getcp3dr( INS_RD( m_op ) ) );
break;
- case 1:
- data = ( data & 0x0000ffff ) | ( readword_masked( address, 0x0000ffff ) << 16 );
+ case RS_CFC:
+ delayed_load( INS_RT( m_op ), getcp3cr( INS_RD( m_op ) ) );
break;
- case 2:
- data = ( data & 0x000000ff ) | ( readword_masked( address, 0x00ffffff ) << 8 );
+ case RS_MTC:
+ setcp3dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_CTC:
+ setcp3cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
+ advance_pc();
+ break;
+
+ case RS_BC:
+ case RS_BC_ALT:
+ switch( INS_BC( m_op ) )
+ {
+ case BC_BCF:
+ bc( 3, SR_CU3, 0 );
+ break;
+
+ case BC_BCT:
+ bc( 3, SR_CU3, 1 );
+ break;
+ }
break;
- case 3:
- data = readword( address );
+ default:
+ advance_pc();
break;
}
+ }
+ break;
- if( m_berr )
+ case OP_LB:
+ {
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
{
- load_bus_error_exception();
+ load_bad_address( address );
+ }
+ else if( breakpoint )
+ {
+ breakpoint_exception();
}
else
{
- delayed_load( INS_RT( m_op ), data );
+ uint32_t data = PSXCPU_BYTE_EXTEND( readbyte( address ) );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
}
}
- }
- break;
-
- case OP_LW:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = load_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_word_address_mask ) != 0 )
- {
- load_bad_address( address );
- }
- else if( breakpoint )
- {
- breakpoint_exception();
- }
- else
+ case OP_LH:
{
- uint32_t data = readword( address );
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
- if( m_berr )
+ if( ( address & m_bad_half_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
{
- load_bus_error_exception();
+ breakpoint_exception();
}
else
{
- delayed_load( INS_RT( m_op ), data );
+ uint32_t data = PSXCPU_WORD_EXTEND( readhalf( address ) );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
}
}
- }
- break;
-
- case OP_LBU:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = load_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_byte_address_mask ) != 0 )
- {
- load_bad_address( address );
- }
- else if( breakpoint )
+ case OP_LWL:
{
- breakpoint_exception();
- }
- else
- {
- uint32_t data = readbyte( address );
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int load_type = address & 3;
+ int breakpoint;
- if( m_berr )
+ address &= ~3;
+ breakpoint = load_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
{
- load_bus_error_exception();
+ load_bad_address( address );
}
- else
+ else if( breakpoint )
{
- delayed_load( INS_RT( m_op ), data );
+ breakpoint_exception();
}
- }
- }
- break;
+ else
+ {
+ uint32_t data = get_register_from_pipeline( INS_RT( m_op ) );
- case OP_LHU:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = load_data_address_breakpoint( address );
+ switch( load_type )
+ {
+ case 0:
+ data = ( data & 0x00ffffff ) | ( readword_masked( address, 0x000000ff ) << 24 );
+ break;
- if( ( address & m_bad_half_address_mask ) != 0 )
- {
- load_bad_address( address );
- }
- else if( breakpoint )
- {
- breakpoint_exception();
+ case 1:
+ data = ( data & 0x0000ffff ) | ( readword_masked( address, 0x0000ffff ) << 16 );
+ break;
+
+ case 2:
+ data = ( data & 0x000000ff ) | ( readword_masked( address, 0x00ffffff ) << 8 );
+ break;
+
+ case 3:
+ data = readword( address );
+ break;
+ }
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
+ }
}
- else
+ break;
+
+ case OP_LW:
{
- uint32_t data = readhalf( address );
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
- if( m_berr )
+ if( ( address & m_bad_word_address_mask ) != 0 )
+ {
+ load_bad_address( address );
+ }
+ else if( breakpoint )
{
- load_bus_error_exception();
+ breakpoint_exception();
}
else
{
- delayed_load( INS_RT( m_op ), data );
+ uint32_t data = readword( address );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
}
}
- }
- break;
-
- case OP_LWR:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = load_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_byte_address_mask ) != 0 )
- {
- load_bad_address( address );
- }
- else if( breakpoint )
+ case OP_LBU:
{
- breakpoint_exception();
- }
- else
- {
- uint32_t data = get_register_from_pipeline( INS_RT( m_op ) );
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
- switch( address & 3 )
+ if( ( address & m_bad_byte_address_mask ) != 0 )
{
- case 0:
- data = readword( address );
- break;
-
- case 1:
- data = ( data & 0xff000000 ) | ( readword_masked( address, 0xffffff00 ) >> 8 );
- break;
-
- case 2:
- data = ( data & 0xffff0000 ) | ( readword_masked( address, 0xffff0000 ) >> 16 );
- break;
-
- case 3:
- data = ( data & 0xffffff00 ) | ( readword_masked( address, 0xff000000 ) >> 24 );
- break;
+ load_bad_address( address );
}
-
- if( m_berr )
+ else if( breakpoint )
{
- load_bus_error_exception();
+ breakpoint_exception();
}
else
{
- delayed_load( INS_RT( m_op ), data );
+ uint32_t data = readbyte( address );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
}
}
- }
- break;
-
- case OP_SB:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = store_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_byte_address_mask ) != 0 )
+ case OP_LHU:
{
- store_bad_address( address );
- }
- else
- {
- int shift = 8 * ( address & 3 );
- writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xff << shift );
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
- if( breakpoint )
+ if( ( address & m_bad_half_address_mask ) != 0 )
{
- breakpoint_exception();
+ load_bad_address( address );
}
- else if( m_berr )
+ else if( breakpoint )
{
- store_bus_error_exception();
+ breakpoint_exception();
}
else
{
- advance_pc();
+ uint32_t data = readhalf( address );
+
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
}
}
- }
- break;
-
- case OP_SH:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = store_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_half_address_mask ) != 0 )
- {
- store_bad_address( address );
- }
- else
+ case OP_LWR:
{
- int shift = 8 * ( address & 2 );
- writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xffff << shift );
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = load_data_address_breakpoint( address );
- if( breakpoint )
+ if( ( address & m_bad_byte_address_mask ) != 0 )
{
- breakpoint_exception();
+ load_bad_address( address );
}
- else if( m_berr )
+ else if( breakpoint )
{
- store_bus_error_exception();
+ breakpoint_exception();
}
else
{
- advance_pc();
- }
- }
- }
- break;
+ uint32_t data = get_register_from_pipeline( INS_RT( m_op ) );
- case OP_SWL:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int save_type = address & 3;
- int breakpoint;
+ switch( address & 3 )
+ {
+ case 0:
+ data = readword( address );
+ break;
- address &= ~3;
- breakpoint = store_data_address_breakpoint( address );
+ case 1:
+ data = ( data & 0xff000000 ) | ( readword_masked( address, 0xffffff00 ) >> 8 );
+ break;
- if( ( address & m_bad_byte_address_mask ) != 0 )
- {
- store_bad_address( address );
- }
- else
- {
- switch( save_type )
- {
- case 0:
- writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 24, 0x000000ff );
- break;
+ case 2:
+ data = ( data & 0xffff0000 ) | ( readword_masked( address, 0xffff0000 ) >> 16 );
+ break;
- case 1:
- writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 16, 0x0000ffff );
- break;
-
- case 2:
- writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 8, 0x00ffffff );
- break;
+ case 3:
+ data = ( data & 0xffffff00 ) | ( readword_masked( address, 0xff000000 ) >> 24 );
+ break;
+ }
- case 3:
- writeword( address, m_r[ INS_RT( m_op ) ] );
- break;
+ if( m_berr )
+ {
+ load_bus_error_exception();
+ }
+ else
+ {
+ delayed_load( INS_RT( m_op ), data );
+ }
}
+ }
+ break;
- if( breakpoint )
- {
- breakpoint_exception();
- }
- else if( m_berr )
+ case OP_SB:
+ {
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
{
- store_bus_error_exception();
+ store_bad_address( address );
}
else
{
- advance_pc();
+ int shift = 8 * ( address & 3 );
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xff << shift );
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
}
}
- }
- break;
-
- case OP_SW:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = store_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_word_address_mask ) != 0 )
+ case OP_SH:
{
- store_bad_address( address );
- }
- else
- {
- writeword( address, m_r[ INS_RT( m_op ) ] );
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
- if( breakpoint )
- {
- breakpoint_exception();
- }
- else if( m_berr )
+ if( ( address & m_bad_half_address_mask ) != 0 )
{
- store_bus_error_exception();
+ store_bad_address( address );
}
else
{
- advance_pc();
+ int shift = 8 * ( address & 2 );
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xffff << shift );
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
}
}
- }
- break;
-
- case OP_SWR:
- {
- uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
- int breakpoint = store_data_address_breakpoint( address );
+ break;
- if( ( address & m_bad_byte_address_mask ) != 0 )
+ case OP_SWL:
{
- store_bad_address( address );
- }
- else
- {
- switch( address & 3 )
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int save_type = address & 3;
+ int breakpoint;
+
+ address &= ~3;
+ breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
{
- case 0:
- writeword( address, m_r[ INS_RT( m_op ) ] );
- break;
+ store_bad_address( address );
+ }
+ else
+ {
+ switch( save_type )
+ {
+ case 0:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 24, 0x000000ff );
+ break;
- case 1:
- writeword_masked( address, m_r[ INS_RT( m_op ) ] << 8, 0xffffff00 );
- break;
+ case 1:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 16, 0x0000ffff );
+ break;
- case 2:
- writeword_masked( address, m_r[ INS_RT( m_op ) ] << 16, 0xffff0000 );
- break;
+ case 2:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 8, 0x00ffffff );
+ break;
- case 3:
- writeword_masked( address, m_r[ INS_RT( m_op ) ] << 24, 0xff000000 );
- break;
+ case 3:
+ writeword( address, m_r[ INS_RT( m_op ) ] );
+ break;
+ }
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
}
+ }
+ break;
+
+ case OP_SW:
+ {
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
- if( breakpoint )
+ if( ( address & m_bad_word_address_mask ) != 0 )
{
- breakpoint_exception();
+ store_bad_address( address );
}
- else if( m_berr )
+ else
+ {
+ writeword( address, m_r[ INS_RT( m_op ) ] );
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
+ }
+ }
+ break;
+
+ case OP_SWR:
+ {
+ uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
+ int breakpoint = store_data_address_breakpoint( address );
+
+ if( ( address & m_bad_byte_address_mask ) != 0 )
{
- store_bus_error_exception();
+ store_bad_address( address );
}
else
{
- advance_pc();
+ switch( address & 3 )
+ {
+ case 0:
+ writeword( address, m_r[ INS_RT( m_op ) ] );
+ break;
+
+ case 1:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << 8, 0xffffff00 );
+ break;
+
+ case 2:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << 16, 0xffff0000 );
+ break;
+
+ case 3:
+ writeword_masked( address, m_r[ INS_RT( m_op ) ] << 24, 0xff000000 );
+ break;
+ }
+
+ if( breakpoint )
+ {
+ breakpoint_exception();
+ }
+ else if( m_berr )
+ {
+ store_bus_error_exception();
+ }
+ else
+ {
+ advance_pc();
+ }
}
}
- }
- break;
+ break;
- case OP_LWC0:
- lwc( 0, SR_CU0 );
- break;
+ case OP_LWC0:
+ lwc( 0, SR_CU0 );
+ break;
- case OP_LWC1:
- lwc( 1, SR_CU1 );
- break;
+ case OP_LWC1:
+ lwc( 1, SR_CU1 );
+ break;
- case OP_LWC2:
- lwc( 2, SR_CU2 );
- break;
+ case OP_LWC2:
+ lwc( 2, SR_CU2 );
+ break;
- case OP_LWC3:
- lwc( 3, SR_CU3 );
- break;
+ case OP_LWC3:
+ lwc( 3, SR_CU3 );
+ break;
- case OP_SWC0:
- swc( 0, SR_CU0 );
- break;
+ case OP_SWC0:
+ swc( 0, SR_CU0 );
+ break;
- case OP_SWC1:
- swc( 1, SR_CU1 );
- break;
+ case OP_SWC1:
+ swc( 1, SR_CU1 );
+ break;
- case OP_SWC2:
- swc( 2, SR_CU2 );
- break;
+ case OP_SWC2:
+ swc( 2, SR_CU2 );
+ break;
- case OP_SWC3:
- swc( 3, SR_CU3 );
- break;
+ case OP_SWC3:
+ swc( 3, SR_CU3 );
+ break;
- default:
- logerror( "%08x: unknown opcode %08x\n", m_pc, m_op );
- stop();
- exception( EXC_RI );
- break;
+ default:
+ logerror( "%08x: unknown opcode %08x\n", m_pc, m_op );
+ stop();
+ exception( EXC_RI );
+ break;
+ }
}
}