(SNES) Rewritten cycle steal code from scratch and nailed it directly in the G65816 CPU core [Angelo Salese, byuu]

This commit is contained in:
Angelo Salese 2012-08-22 20:16:55 +00:00
parent 6f13297dcf
commit 170b6ae5c2
4 changed files with 31 additions and 151 deletions

View File

@ -143,6 +143,9 @@ extern void g65816i_set_reg_E(g65816i_cpu_struct *cpustate, int regnum, uint val
extern void g65816i_set_line_E(g65816i_cpu_struct *cpustate, int line, int state);
extern int g65816i_execute_E(g65816i_cpu_struct *cpustate, int cycles);
extern int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr);
void (*const *const g65816i_opcodes[5])(g65816i_cpu_struct *cpustate) =
{
g65816i_opcodes_M0X0,
@ -525,6 +528,22 @@ CPU_GET_INFO( g65816 )
SNES specific, used to handle master cycles
*/
int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr)
{
if(cpustate->cpu_type == CPU_TYPE_G65816)
return 0;
if(addr & 0x408000) {
if(addr & 0x800000) return (1) ? 6 : 8; // TODO: fastROM setting
return 8;
}
if((addr + 0x6000) & 0x4000) return 8;
if((addr - 0x4000) & 0x7e00) return 6;
return 12;
}
static CPU_INIT( 5a22 )
{
g65816i_cpu_struct *cpustate = get_safe_token(device);

View File

@ -103,6 +103,7 @@ struct _g65816i_cpu_struct
void (*set_reg)(g65816i_cpu_struct *cpustate, int regnum, uint val);
void (*set_line)(g65816i_cpu_struct *cpustate, int line, int state);
int (*execute)(g65816i_cpu_struct *cpustate, int cycles);
int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr);
uint source;
uint destination;
int ICount;
@ -114,6 +115,7 @@ extern uint (*const g65816i_get_reg[])(g65816i_cpu_struct *cpustate, int regnum)
extern void (*const g65816i_set_reg[])(g65816i_cpu_struct *cpustate, int regnum, uint val);
extern void (*const g65816i_set_line[])(g65816i_cpu_struct *cpustate, int line, int state);
extern int (*const g65816i_execute[])(g65816i_cpu_struct *cpustate, int cycles);
extern int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr);
#define REGISTER_A cpustate->a /* Accumulator */
#define REGISTER_B cpustate->b /* Accumulator hi byte */
@ -244,6 +246,7 @@ INLINE void g65816i_set_execution_mode(g65816i_cpu_struct *cpustate, uint mode)
#define CLK_W_SIY 5
#define CLK(A) CLOCKS -= (cpustate->cpu_type == CPU_TYPE_G65816 ? A : A*6)
#define CLK_BUS(A) CLOCKS -= A
#define USE_ALL_CLKS() CLOCKS = 0

View File

@ -59,12 +59,14 @@
INLINE uint g65816i_read_8_normal(g65816i_cpu_struct *cpustate, uint address)
{
address = ADDRESS_65816(address);
CLOCKS -= (bus_5A22_cycle_burst(cpustate,address));
return g65816_read_8(address);
}
INLINE uint g65816i_read_8_immediate(g65816i_cpu_struct *cpustate, uint address)
{
address = ADDRESS_65816(address);
CLOCKS -= (bus_5A22_cycle_burst(cpustate,address));
return g65816_read_8_immediate(address);
}
@ -76,6 +78,7 @@ INLINE uint g65816i_read_8_direct(g65816i_cpu_struct *cpustate, uint address)
#else
address = ADDRESS_65816(address);
#endif
CLOCKS -= (bus_5A22_cycle_burst(cpustate,address));
return g65816_read_8(address);
}
@ -90,6 +93,7 @@ INLINE uint g65816i_read_8_vector(g65816i_cpu_struct *cpustate, uint address)
INLINE void g65816i_write_8_normal(g65816i_cpu_struct *cpustate, uint address, uint value)
{
address = ADDRESS_65816(address);
CLOCKS -= (bus_5A22_cycle_burst(cpustate,address));
g65816_write_8(address, MAKE_UINT_8(value));
}
@ -101,6 +105,7 @@ INLINE void g65816i_write_8_direct(g65816i_cpu_struct *cpustate, uint address, u
#else
address = ADDRESS_65816(address);
#endif
CLOCKS -= (bus_5A22_cycle_burst(cpustate,address));
g65816_write_8(address, MAKE_UINT_8(value));
}

View File

@ -13,6 +13,10 @@
Thanks to Anomie for invaluable technical information.
Thanks to byuu for invaluable technical information.
TODO:
- DMA takes some Master CPU clock cycles that aren't taken into account
for now.
***************************************************************************/
#define __MACHINE_SNES_C
@ -55,8 +59,6 @@ struct snes_cart_info snes_cart;
#include "machine/snes7110.c"
#include "machine/snesbsx.c"
#define USE_CYCLE_STEAL 1
// ST-010 and ST-011 RAM interface
UINT8 st010_read_ram(snes_state *state, UINT16 addr)
{
@ -892,70 +894,6 @@ address | | | | | | |
*/
#if USE_CYCLE_STEAL
/*FIXME: missing work RAM access steal / we need to do this less "aggressive" otherwise we lose too much CPU horsepower, why? */
static int snes_bank_0x00_0x3f_cycles(running_machine &machine,UINT32 offset)
{
/*
$00-$3F | $0000-$1FFF | Slow | Address Bus A + /WRAM (mirror $7E:0000-$1FFF)
| $2000-$20FF | Fast | Address Bus A
| $2100-$21FF | Fast | Address Bus B
| $2200-$3FFF | Fast | Address Bus A
| $4000-$41FF | XSlow | Internal CPU registers (see Note 1 below)
| $4200-$43FF | Fast | Internal CPU registers (see Note 1 below)
| $4400-$5FFF | Fast | Address Bus A
| $6000-$7FFF | Slow | Address Bus A
| $8000-$FFFF | Slow | Address Bus A + /CART
*/
if(((offset & 0xff00) == 0x4000) || ((offset & 0xff00) == 0x4100))
return 0; //TODO: 12
if(((offset & 0xff00) == 0x4200) || ((offset & 0xff00) == 0x4300))
return 0; //TODO: 6
if((offset & 0xff00) <= 0x1f00)
return 0; //TODO: 8
if((offset & 0xff00) >= 0x6000)
return 8;
return 0; //TODO: 6
}
static int snes_bank_0x80_0xbf_cycles(running_machine &machine,UINT32 offset)
{
/*
$80-$BF | $0000-$1FFF | Slow | Address Bus A + /WRAM (mirror $7E:0000-$1FFF)
| $2000-$20FF | Fast | Address Bus A
| $2100-$21FF | Fast | Address Bus B
| $2200-$3FFF | Fast | Address Bus A
| $4000-$41FF | XSlow | Internal CPU registers (see Note 1 below)
| $4200-$43FF | Fast | Internal CPU registers (see Note 1 below)
| $4400-$5FFF | Fast | Address Bus A
| $6000-$7FFF | Slow | Address Bus A
| $8000-$FFFF | Note2 | Address Bus A + /CART
*/
if(((offset & 0xff00) == 0x4000) || ((offset & 0xff00) == 0x4100))
return 0; //TODO: 12
if(((offset & 0xff00) == 0x4200) || ((offset & 0xff00) == 0x4300))
return 0; //TODO: 6
if((offset & 0xff00) <= 0x1f00)
return 0; //TODO: 8
if(((offset & 0xff00) >= 0x6000) && ((offset & 0xff00) <= 0x7f00))
return 0; //TODO: 8
if(((offset & 0xff00) >= 0x8000) && ((offset & 0xff00) <= 0xff00))
return (snes_ram[MEMSEL] & 1) ? 6 : 8;
return 0; //TODO: 6
}
#endif
/* 0x000000 - 0x2fffff */
READ8_HANDLER( snes_r_bank1 )
{
@ -1007,11 +945,6 @@ READ8_HANDLER( snes_r_bank1 )
else
value = snes_ram[offset];
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset));
#endif
return value;
}
@ -1074,11 +1007,6 @@ READ8_HANDLER( snes_r_bank2 )
else
value = snes_ram[0x300000 + offset];
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset));
#endif
return value;
}
@ -1117,11 +1045,6 @@ READ8_HANDLER( snes_r_bank3 )
else /* Mode 21 & 25 + SuperFX games */
value = snes_ram[0x400000 + offset];
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -8);
#endif
return value;
}
@ -1166,11 +1089,6 @@ READ8_HANDLER( snes_r_bank4 )
else if (state->m_cart[0].mode & 0x0a) /* Mode 21 & 25 */
value = snes_ram[0x600000 + offset];
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -8);
#endif
return value;
}
@ -1204,11 +1122,6 @@ READ8_HANDLER( snes_r_bank5 )
else
value = snes_ram[0x700000 + offset];
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -8);
#endif
return value;
}
@ -1254,11 +1167,6 @@ READ8_HANDLER( snes_r_bank6 )
else
value = snes_ram[0x800000 + offset];
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -snes_bank_0x80_0xbf_cycles(space->machine(), offset));
#endif
return value;
}
@ -1318,11 +1226,6 @@ READ8_HANDLER( snes_r_bank7 )
else /* Mode 21 & 25 + SuperFX Games */
value = snes_ram[0xc00000 + offset];
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -((snes_ram[MEMSEL] & 1) ? 6 : 8));
#endif
return value;
}
@ -1376,11 +1279,6 @@ WRITE8_HANDLER( snes_w_bank1 )
dsp_set_sr(data);
else
logerror( "(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset );
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset));
#endif
}
/* 0x300000 - 0x3fffff */
@ -1438,11 +1336,6 @@ WRITE8_HANDLER( snes_w_bank2 )
dsp_set_sr(data);
else
logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x300000);
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset));
#endif
}
/* 0x600000 - 0x6fffff */
@ -1479,11 +1372,6 @@ WRITE8_HANDLER( snes_w_bank4 )
}
else if (state->m_cart[0].mode & 0x0a)
logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x600000);
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -8);
#endif
}
/* 0x700000 - 0x7dffff */
@ -1506,11 +1394,6 @@ WRITE8_HANDLER( snes_w_bank5 )
}
else if (state->m_cart[0].mode & 0x0a)
logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x700000);
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -8);
#endif
}
@ -1562,11 +1445,6 @@ WRITE8_HANDLER( snes_w_bank6 )
dsp_set_sr(data);
else
logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x800000);
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -snes_bank_0x80_0xbf_cycles(space->machine(), offset));
#endif
}
@ -1617,11 +1495,6 @@ WRITE8_HANDLER( snes_w_bank7 )
}
else if (state->m_cart[0].mode & 0x0a)
logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0xc00000);
#if USE_CYCLE_STEAL
if(!space->debugger_access())
device_adjust_icount(&space->device(), -((snes_ram[MEMSEL] & 1) ? 6 : 8));
#endif
}
@ -2143,12 +2016,6 @@ INLINE void snes_dma_transfer( address_space *space, UINT8 dma, UINT32 abus, UIN
{
snes_state *state = space->machine().driver_data<snes_state>();
#if USE_CYCLE_STEAL
/* every byte transfer takes 8 master cycles */
// FIXME: this cycle steal makes Final Fantasy VI (III in US) very glitchy!
// device_adjust_icount(&space->device(),-8);
#endif
if (state->m_dma_channel[dma].dmap & 0x80) /* PPU->CPU */
{
if (bbus == 0x2180 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000))
@ -2355,11 +2222,6 @@ static void snes_dma( address_space *space, UINT8 channels )
/* FIXME: we also need to round to the nearest 8 master cycles */
#if USE_CYCLE_STEAL
/* overhead steals 8 master cycles, correct? */
device_adjust_icount(&space->device(),-8);
#endif
/* Assume priority of the 8 DMA channels is 0-7 */
for (i = 0; i < 8; i++)
{
@ -2468,18 +2330,9 @@ static void snes_dma( address_space *space, UINT8 channels )
/* We're done, so write the new abus back to the registers */
state->m_dma_channel[i].src_addr = abus;
state->m_dma_channel[i].trans_size = 0;
#if USE_CYCLE_STEAL
/* active channel takes 8 master cycles */
device_adjust_icount(&space->device(),-8);
#endif
}
}
/* finally, take yet another 8 master cycles for the aforementioned overhead */
#if USE_CYCLE_STEAL
device_adjust_icount(&space->device(),-8);
#endif
}
READ8_HANDLER( superfx_r_bank1 )