summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author smf- <smf-@users.noreply.github.com>2017-09-22 20:32:54 +0100
committer smf- <smf-@users.noreply.github.com>2017-09-22 20:40:32 +0100
commit7b87813ea9f3cf04775b4e0baadd8a2bd830e574 (patch)
treef65b983604454817b4675dd604ef3b0aa3932dce /src
parent7f1a839801a9e9d79d418c1fcbf380ebc588c834 (diff)
Implemented program counter break point to PlayStation CPU & re-added PlayStation EXE, CPE & PSF loading. [smf]
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/psx/psx.cpp1530
-rw-r--r--src/devices/cpu/psx/psx.h26
-rw-r--r--src/devices/cpu/psx/psxdefs.h3
-rw-r--r--src/mame/drivers/psx.cpp411
4 files changed, 1204 insertions, 766 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;
+ }
}
}
diff --git a/src/devices/cpu/psx/psx.h b/src/devices/cpu/psx/psx.h
index 7b4793fc3bd..da70d2c300c 100644
--- a/src/devices/cpu/psx/psx.h
+++ b/src/devices/cpu/psx/psx.h
@@ -24,12 +24,15 @@
// interrupts
-#define PSXCPU_IRQ0 ( 0 )
-#define PSXCPU_IRQ1 ( 1 )
-#define PSXCPU_IRQ2 ( 2 )
-#define PSXCPU_IRQ3 ( 3 )
-#define PSXCPU_IRQ4 ( 4 )
-#define PSXCPU_IRQ5 ( 5 )
+enum
+{
+ PSXCPU_IRQ0 = 0,
+ PSXCPU_IRQ1,
+ PSXCPU_IRQ2,
+ PSXCPU_IRQ3,
+ PSXCPU_IRQ4,
+ PSXCPU_IRQ5,
+};
// register enumeration
@@ -97,6 +100,14 @@ enum
PSXCPU_CP2CR30, PSXCPU_CP2CR31
};
+// delay slot sentinels
+
+enum
+{
+ PSXCPU_DELAYR_PC = 32,
+ PSXCPU_DELAYR_NOTPC = 33
+};
+
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
@@ -293,7 +304,7 @@ protected:
void commit_delayed_load();
void set_pc( unsigned pc );
void fetch_next_op();
- int advance_pc();
+ void advance_pc();
void load( uint32_t reg, uint32_t value );
void delayed_load( uint32_t reg, uint32_t value );
void branch( uint32_t address );
@@ -307,6 +318,7 @@ protected:
void store_bus_error_exception();
void load_bad_address( uint32_t address );
void store_bad_address( uint32_t address );
+ int program_counter_breakpoint();
int data_address_breakpoint( int dcic_rw, int dcic_status, uint32_t address );
int load_data_address_breakpoint( uint32_t address );
int store_data_address_breakpoint( uint32_t address );
diff --git a/src/devices/cpu/psx/psxdefs.h b/src/devices/cpu/psx/psxdefs.h
index fde2456b515..3939254ac50 100644
--- a/src/devices/cpu/psx/psxdefs.h
+++ b/src/devices/cpu/psx/psxdefs.h
@@ -6,9 +6,6 @@
#pragma once
-#define PSXCPU_DELAYR_PC ( 32 )
-#define PSXCPU_DELAYR_NOTPC ( 33 )
-
#define PSXCPU_BYTE_EXTEND( a ) ( (int32_t)(int8_t)a )
#define PSXCPU_WORD_EXTEND( a ) ( (int32_t)(int16_t)a )
diff --git a/src/mame/drivers/psx.cpp b/src/mame/drivers/psx.cpp
index 453b030ce6f..b1e07a4c460 100644
--- a/src/mame/drivers/psx.cpp
+++ b/src/mame/drivers/psx.cpp
@@ -1,9 +1,9 @@
-// license:BSD-3-Clause
+// license:GPL-2.0+
// copyright-holders:smf, pSXAuthor, R. Belmont
/***************************************************************************
- Sony Playstaion
- ===============
+ Sony PlayStation
+ ================
Preliminary driver by smf
Additional development by pSXAuthor and R. Belmont
@@ -25,6 +25,7 @@
#include "softlist.h"
#include "speaker.h"
+#include <zlib.h>
#define PSXCD_TAG "psxcd"
@@ -32,14 +33,13 @@ class psx1_state : public driver_device
{
public:
psx1_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag) ,
+ : driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_ram(*this, "maincpu:ram")
{
}
- uint8_t *m_exe_buffer;
- int m_exe_size;
+ std::vector<uint8_t> m_exe_buffer;
int m_cd_param_p;
int m_cd_result_p;
int m_cd_result_c;
@@ -51,6 +51,14 @@ public:
uint8_t m_cd_result[8];
DECLARE_MACHINE_RESET(psx);
inline void ATTR_PRINTF(3,4) verboselog( int n_level, const char *s_fmt, ... );
+ void psxexe_conv32(uint32_t *uint32);
+ int load_psxexe(std::vector<uint8_t> buffer);
+ void cpe_set_register(int r, int v);
+ int load_cpe(std::vector<uint8_t> buffer);
+ int load_psf(std::vector<uint8_t> buffer);
+ DECLARE_READ16_MEMBER(parallel_r);
+ DECLARE_WRITE16_MEMBER(parallel_w);
+ DECLARE_QUICKLOAD_LOAD_MEMBER(psx_exe_load);
void cd_dma_read( uint32_t *p_n_psxram, uint32_t n_address, int32_t n_size );
void cd_dma_write( uint32_t *p_n_psxram, uint32_t n_address, int32_t n_size );
required_device<psxcpu_device> m_maincpu;
@@ -73,6 +81,392 @@ inline void ATTR_PRINTF(3,4) psx1_state::verboselog( int n_level, const char *s
}
}
+void psx1_state::psxexe_conv32(uint32_t *uint32)
+{
+ uint8_t *uint8 = (uint8_t *)uint32;
+
+ *(uint32) = uint8[0] | (uint8[1] << 8) | (uint8[2] << 16) | (uint8[3] << 24);
+}
+
+int psx1_state::load_psxexe(std::vector<uint8_t> buffer)
+{
+ struct PSXEXE_HEADER
+ {
+ uint8_t id[8];
+ uint32_t text; /* SCE only */
+ uint32_t data; /* SCE only */
+ uint32_t pc0;
+ uint32_t gp0; /* SCE only */
+ uint32_t t_addr;
+ uint32_t t_size;
+ uint32_t d_addr; /* SCE only */
+ uint32_t d_size; /* SCE only */
+ uint32_t b_addr; /* SCE only */
+ uint32_t b_size; /* SCE only */
+ uint32_t s_addr;
+ uint32_t s_size;
+ uint32_t SavedSP;
+ uint32_t SavedFP;
+ uint32_t SavedGP;
+ uint32_t SavedRA;
+ uint32_t SavedS0;
+ uint8_t dummy[0x800 - 76];
+ };
+
+ struct PSXEXE_HEADER *psxexe_header = reinterpret_cast<struct PSXEXE_HEADER *>(&buffer[0]);
+
+ if (buffer.size() >= sizeof(struct PSXEXE_HEADER) &&
+ memcmp(psxexe_header->id, "PS-X EXE", 8) == 0)
+ {
+ psxexe_conv32(&psxexe_header->text);
+ psxexe_conv32(&psxexe_header->data);
+ psxexe_conv32(&psxexe_header->pc0);
+ psxexe_conv32(&psxexe_header->gp0);
+ psxexe_conv32(&psxexe_header->t_addr);
+ psxexe_conv32(&psxexe_header->t_size);
+ psxexe_conv32(&psxexe_header->d_addr);
+ psxexe_conv32(&psxexe_header->d_size);
+ psxexe_conv32(&psxexe_header->b_addr);
+ psxexe_conv32(&psxexe_header->b_size);
+ psxexe_conv32(&psxexe_header->s_addr);
+ psxexe_conv32(&psxexe_header->s_size);
+ psxexe_conv32(&psxexe_header->SavedSP);
+ psxexe_conv32(&psxexe_header->SavedFP);
+ psxexe_conv32(&psxexe_header->SavedGP);
+ psxexe_conv32(&psxexe_header->SavedRA);
+ psxexe_conv32(&psxexe_header->SavedS0);
+
+ /* todo: check size.. */
+
+ logerror("psx_exe_load: pc %08x\n", psxexe_header->pc0);
+ logerror("psx_exe_load: org %08x\n", psxexe_header->t_addr);
+ logerror("psx_exe_load: len %08x\n", psxexe_header->t_size);
+ logerror("psx_exe_load: sp %08x\n", psxexe_header->s_addr);
+ logerror("psx_exe_load: len %08x\n", psxexe_header->s_size);
+
+ uint8_t *ram_pointer = m_ram->pointer();
+ uint32_t ram_size = m_ram->size();
+
+ uint8_t *text = reinterpret_cast<uint8_t *>(&buffer[sizeof(struct PSXEXE_HEADER)]);
+
+ uint32_t address = psxexe_header->t_addr;
+ uint32_t size = psxexe_header->t_size;
+ while (size != 0)
+ {
+ ram_pointer[BYTE4_XOR_LE(address++) % ram_size] = *(text++);
+ size--;
+ }
+
+ m_maincpu->set_state_int(PSXCPU_PC, psxexe_header->pc0);
+ m_maincpu->set_state_int(PSXCPU_R28, psxexe_header->gp0);
+ uint32_t stack = psxexe_header->s_addr + psxexe_header->s_size;
+ if (stack != 0)
+ {
+ m_maincpu->set_state_int(PSXCPU_R29, stack);
+ m_maincpu->set_state_int(PSXCPU_R30, stack);
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
+void psx1_state::cpe_set_register(int r, int v)
+{
+ if (r < 0x80 && (r % 4) == 0)
+ {
+ logerror("psx_exe_load: r%-2d %08x\n", r / 4, v);
+ m_maincpu->set_state_int(PSXCPU_R0 + (r / 4), v);
+ }
+ else if (r == 0x80)
+ {
+ logerror("psx_exe_load: lo %08x\n", v);
+ m_maincpu->set_state_int(PSXCPU_LO, v);
+ }
+ else if (r == 0x84)
+ {
+ logerror("psx_exe_load: hi %08x\n", v);
+ m_maincpu->set_state_int(PSXCPU_HI, v);
+ }
+ else if (r == 0x88)
+ {
+ logerror("psx_exe_load: sr %08x\n", v);
+ m_maincpu->set_state_int(PSXCPU_CP0R12, v);
+ }
+ else if (r == 0x8c)
+ {
+ logerror("psx_exe_load: cause %08x\n", v);
+ m_maincpu->set_state_int(PSXCPU_CP0R13, v);
+ }
+ else if (r == 0x90)
+ {
+ logerror("psx_exe_load: pc %08x\n", v);
+ m_maincpu->set_state_int(PSXCPU_PC, v);
+ }
+ else if (r == 0x94)
+ {
+ logerror("psx_exe_load: prid %08x\n", v);
+ m_maincpu->set_state_int(PSXCPU_CP0R15, v);
+ }
+ else
+ {
+ logerror("psx_exe_load: invalid register %04x/%08x\n", r, v);
+ }
+}
+
+int psx1_state::load_cpe(std::vector<uint8_t> buffer)
+{
+ if (buffer.size() >= 4 &&
+ memcmp(reinterpret_cast<void *>(&buffer[0]), "CPE\001", 4) == 0)
+ {
+ int offset = 4;
+
+ for (;;)
+ {
+ if (offset >= buffer.size() || buffer[offset] > 8)
+ {
+ break;
+ }
+
+ switch (buffer[offset++])
+ {
+ case 0:
+ /* end of file */
+ return 1;
+
+ case 1:
+ /* read bytes */
+ {
+ unsigned int address = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24);
+ unsigned int size = buffer[offset + 4] | (buffer[offset + 5] << 8) | (buffer[offset + 6] << 16) | (buffer[offset + 7] << 24);
+
+ uint8_t *ram_pointer = m_ram->pointer();
+ uint32_t ram_size = m_ram->size();
+
+ offset += 8;
+
+ logerror("psx_exe_load: org %08x\n", address);
+ logerror("psx_exe_load: len %08x\n", size);
+
+ while (size > 0)
+ {
+ ram_pointer[BYTE4_XOR_LE(address) % ram_size] = buffer[offset++];
+ address++;
+ size--;
+ }
+ }
+ break;
+
+ case 2:
+ /* run address: not tested */
+ {
+ unsigned int v = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24);
+
+ offset += 4;
+
+ cpe_set_register(0x90, v);
+ }
+ break;
+
+ case 3:
+ /* set reg to longword */
+ {
+ unsigned int r = buffer[offset] | (buffer[offset + 1] << 8);
+ unsigned int v = buffer[offset + 2] | (buffer[offset + 3] << 8) | (buffer[offset + 4] << 16) | (buffer[offset + 5] << 24);
+
+ offset += 6;
+
+ cpe_set_register(r, v);
+ }
+ break;
+
+ case 4:
+ /* set reg to word: not tested */
+ {
+ unsigned int r = buffer[offset] | (buffer[offset + 1] << 8);
+ unsigned int v = buffer[offset + 2] | (buffer[offset + 3] << 8);
+
+ offset += 4;
+
+ cpe_set_register(r, v);
+ }
+ break;
+
+ case 5:
+ /* set reg to byte: not tested */
+ {
+ unsigned int r = buffer[offset] | (buffer[offset + 1] << 8);
+ unsigned int v = buffer[offset + 2];
+
+ offset += 3;
+
+ cpe_set_register(r, v);
+ }
+ break;
+
+ case 6:
+ /* set reg to 3-byte: not tested */
+ {
+ unsigned int r = buffer[offset] | (buffer[offset + 1] << 8);
+ unsigned int v = buffer[offset + 2] | (buffer[offset + 3] << 8) | (buffer[offset + 4] << 16);
+
+ offset += 5;
+
+ cpe_set_register(r, v);
+ }
+ break;
+
+ case 7:
+ /* workspace: not tested */
+ offset += 4;
+ break;
+
+ case 8:
+ /* unit */
+ {
+ int unit = buffer[offset + 0];
+
+ offset++;
+
+ logerror("psx_exe_load: unit %08x\n", unit);
+ }
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int psx1_state::load_psf(std::vector<uint8_t> buffer)
+{
+ unsigned long crc;
+ unsigned long compressed_size;
+ unsigned char *compressed_buffer;
+ unsigned long uncompressed_size;
+ std::vector<uint8_t> uncompressed_buffer;
+
+ struct PSF_HEADER
+ {
+ unsigned char id[4];
+ uint32_t reserved_size;
+ uint32_t exe_size;
+ uint32_t exe_crc;
+ };
+
+ struct PSF_HEADER *psf_header = reinterpret_cast<struct PSF_HEADER *>(&buffer[0]);
+
+ if (buffer.size() >= sizeof(struct PSF_HEADER) &&
+ memcmp(reinterpret_cast<void *>(&buffer[0]), "PSF", 3) == 0)
+ {
+ psxexe_conv32(&psf_header->reserved_size);
+ psxexe_conv32(&psf_header->exe_size);
+ psxexe_conv32(&psf_header->exe_crc);
+
+ logerror("psx_exe_load: reserved_size %08x\n", psf_header->reserved_size);
+ logerror("psx_exe_load: exe_size %08x\n", psf_header->exe_size);
+ logerror("psx_exe_load: exe_crc %08x\n", psf_header->exe_crc);
+
+ compressed_size = psf_header->exe_size;
+ compressed_buffer = reinterpret_cast<Bytef *>(&buffer[sizeof(struct PSF_HEADER) + psf_header->reserved_size]);
+
+ crc = crc32(crc32(0L, Z_NULL, 0), compressed_buffer, compressed_size);
+ if (crc != psf_header->exe_crc)
+ {
+ logerror("psx_exe_load: psf invalid crc\n");
+ return 0;
+ }
+
+ uncompressed_size = 0x200000;
+ uncompressed_buffer.resize(uncompressed_size);
+
+ if (uncompress(reinterpret_cast<Bytef *>(&uncompressed_buffer[0]), &uncompressed_size, compressed_buffer, compressed_size) != Z_OK)
+ {
+ logerror("psx_exe_load: psf uncompress failed\n");
+ }
+ else
+ {
+ uncompressed_buffer.resize(uncompressed_size);
+
+ if (!load_psxexe(uncompressed_buffer))
+ {
+ logerror("psx_exe_load: psf load failed\n");
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+READ16_MEMBER(psx1_state::parallel_r)
+{
+ const uint16_t bootloader[] =
+ {
+ 0x00b0, 0x1f00, 0x694c, 0x6563, 0x736e, 0x6465, 0x6220, 0x2079,
+ 0x6f53, 0x796e, 0x4320, 0x6d6f, 0x7570, 0x6574, 0x2072, 0x6e45,
+ 0x6574, 0x7472, 0x6961, 0x6d6e, 0x6e65, 0x2074, 0x6e49, 0x2e63,
+ 0x1f00, 0x3c08, 0x8000, 0x3c09, 0x000c, 0x3529, 0x00fc, 0x8d0a,
+ 0xfffc, 0x2529, 0x0044, 0xad2a, 0xfffc, 0x0520, 0xfffc, 0x2508,
+ 0x8003, 0x3c08, 0x1800, 0x4088, 0xffff, 0x3c08, 0xffff, 0x3508,
+ 0x5800, 0x4088, 0xa180, 0x3c08, 0x0008, 0x03e0, 0x3800, 0x4088,
+ 0x1f00, 0x3c1a, 0x0100, 0x275a, 0x0008, 0x0340, 0x0010, 0x4200,
+ 0x3800, 0x4080, 0x1800, 0x4080, 0x5800, 0x4080, 0x1f00, 0x3c08,
+ 0x0000, 0xad00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+ };
+
+ if (m_exe_buffer.size() != 0 && offset >= 0x40 && offset <= 0x8f)
+ {
+ return bootloader[offset - 0x40];
+ }
+
+ return 0;
+}
+
+WRITE16_MEMBER(psx1_state::parallel_w)
+{
+ if (m_exe_buffer.size() != 0)
+ {
+ if (load_psxexe(m_exe_buffer) ||
+ load_cpe(m_exe_buffer) ||
+ load_psf(m_exe_buffer))
+ {
+ // stop the cpu from advancing to the next instruction, otherwise it would skip the exe's first instruction
+ m_maincpu->set_state_int(PSXCPU_DELAYR, PSXCPU_DELAYR_PC);
+ m_maincpu->set_state_int(PSXCPU_DELAYV, m_maincpu->state_int(PSXCPU_PC));
+
+ // workround to fix controller in amidog tests that do not initialise the sio registers
+ m_maincpu->space(AS_PROGRAM).write_word(0x1f80104e, 0x0088);
+ m_maincpu->space(AS_PROGRAM).write_word(0x1f801048, 0x000d);
+
+ // stop on the first instruction of the exe if the debugger is active
+ machine().debug_break();
+ }
+ else
+ {
+ logerror("psx_exe_load: invalid exe\n");
+ m_maincpu->reset();
+ }
+
+ m_exe_buffer.resize(0);
+ }
+}
+
+QUICKLOAD_LOAD_MEMBER(psx1_state, psx_exe_load)
+{
+ m_exe_buffer.resize(quickload_size);
+
+ if (image.fread(reinterpret_cast<void *>(&m_exe_buffer[0]), quickload_size) != quickload_size)
+ {
+ m_exe_buffer.resize(0);
+ return image_init_result::FAIL;
+ }
+
+ return image_init_result::PASS;
+}
void psx1_state::cd_dma_read( uint32_t *p_n_psxram, uint32_t n_address, int32_t n_size )
{
@@ -87,6 +481,7 @@ void psx1_state::cd_dma_write( uint32_t *p_n_psxram, uint32_t n_address, int32_t
}
static ADDRESS_MAP_START( psx_map, AS_PROGRAM, 32, psx1_state )
+ AM_RANGE(0x1f000000, 0x1f0001ff) AM_READWRITE16(parallel_r, parallel_w, 0xffffffff)
ADDRESS_MAP_END
static ADDRESS_MAP_START( subcpu_map, AS_PROGRAM, 8, psx1_state )
@@ -121,6 +516,8 @@ static MACHINE_CONFIG_START( psj )
MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
+ MCFG_QUICKLOAD_ADD("quickload", psx1_state, psx_exe_load, "cpe,exe,psf,psx", 0)
+
MCFG_SOFTWARE_LIST_ADD("cd_list","psx")
MCFG_DEVICE_MODIFY( "maincpu" )
@@ -167,6 +564,8 @@ static MACHINE_CONFIG_START( pse )
MCFG_SOUND_ROUTE( 0, "lspeaker", 1.00 )
MCFG_SOUND_ROUTE( 1, "rspeaker", 1.00 )
+ MCFG_QUICKLOAD_ADD("quickload", psx1_state, psx_exe_load, "cpe,exe,psf,psx", 0)
+
MCFG_SOFTWARE_LIST_ADD("cd_list","psx")
MCFG_DEVICE_MODIFY( "maincpu" )