32x: start reworking sheduling

This commit is contained in:
notaz 2013-07-07 01:05:11 +03:00
parent 9b5713af95
commit ed4402a7df
17 changed files with 180 additions and 163 deletions

View file

@ -120,10 +120,16 @@ void p32x_reset_sh2s(void)
sh2_set_vbr(1, vbr);
// program will set S_OK
}
msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDoneT();
}
void Pico32xInit(void)
{
if (msh2.mult_m68k_to_sh2 == 0 || msh2.mult_sh2_to_m68k == 0)
Pico32xSetClocks(PICO_MSH2_HZ, 0);
if (ssh2.mult_m68k_to_sh2 == 0 || ssh2.mult_sh2_to_m68k == 0)
Pico32xSetClocks(0, PICO_MSH2_HZ);
}
void PicoPower32x(void)
@ -199,81 +205,76 @@ static void p32x_start_blank(void)
p32x_poll_event(3, 1);
}
static __inline void run_m68k(int cyc)
#define sync_sh2s_normal p32x_sync_sh2s
//#define sync_sh2s_lockstep p32x_sync_sh2s
void sync_sh2s_normal(unsigned int m68k_target)
{
pprof_start(m68k);
unsigned int target = m68k_target;
int msh2_cycles, ssh2_cycles;
int done;
p32x_poll_event(3, 0);
#if defined(EMU_C68K)
PicoCpuCM68k.cycles = cyc;
CycloneRun(&PicoCpuCM68k);
SekCycleCnt += cyc - PicoCpuCM68k.cycles;
#elif defined(EMU_M68K)
SekCycleCnt += m68k_execute(cyc);
#elif defined(EMU_F68K)
SekCycleCnt += fm68k_emulate(cyc+1, 0, 0);
#endif
elprintf(EL_32X, "sh2 sync to %u (%u)", m68k_target, SekCycleCnt);
pprof_end(m68k);
}
if (!(Pico32x.regs[0] & P32XS_nRES))
return; // rare
// ~1463.8, but due to cache misses and slow mem
// it's much lower than that
//#define SH2_LINE_CYCLES 735
#define CYCLES_M68K2MSH2(x) (((x) * p32x_msh2_multiplier) >> 10)
#define CYCLES_M68K2SSH2(x) (((x) * p32x_ssh2_multiplier) >> 10)
{
msh2_cycles = C_M68K_TO_SH2(msh2, target - msh2.m68krcycles_done);
ssh2_cycles = C_M68K_TO_SH2(ssh2, target - ssh2.m68krcycles_done);
#define PICO_32X
#define CPUS_RUN_SIMPLE(m68k_cycles,s68k_cycles) \
{ \
int slice; \
SekCycleAim += m68k_cycles; \
while (SekCycleCnt < SekCycleAim) { \
slice = SekCycleCnt; \
run_m68k(SekCycleAim - SekCycleCnt); \
if (!(Pico32x.regs[0] & P32XS_nRES)) \
continue; /* SH2s reseting */ \
slice = SekCycleCnt - slice; /* real count from 68k */ \
if (SekCycleCnt < SekCycleAim) \
elprintf(EL_32X, "slice %d", slice); \
if (!(Pico32x.emu_flags & (P32XF_SSH2POLL|P32XF_SSH2VPOLL))) { \
pprof_start(ssh2); \
sh2_execute(&ssh2, CYCLES_M68K2SSH2(slice)); \
pprof_end(ssh2); \
} \
if (!(Pico32x.emu_flags & (P32XF_MSH2POLL|P32XF_MSH2VPOLL))) { \
pprof_start(msh2); \
sh2_execute(&msh2, CYCLES_M68K2MSH2(slice)); \
pprof_end(msh2); \
} \
pprof_start(dummy); \
pprof_end(dummy); \
} \
while (msh2_cycles > 0 || ssh2_cycles > 0) {
elprintf(EL_32X, "sh2 exec %u,%u->%u",
msh2.m68krcycles_done, ssh2.m68krcycles_done, target);
if (Pico32x.emu_flags & (P32XF_SSH2POLL|P32XF_SSH2VPOLL)) {
ssh2.m68krcycles_done = target;
ssh2_cycles = 0;
}
else if (ssh2_cycles > 0) {
done = sh2_execute(&ssh2, ssh2_cycles);
ssh2.m68krcycles_done += C_SH2_TO_M68K(ssh2, done);
ssh2_cycles = C_M68K_TO_SH2(ssh2, target - ssh2.m68krcycles_done);
}
if (Pico32x.emu_flags & (P32XF_MSH2POLL|P32XF_MSH2VPOLL)) {
msh2.m68krcycles_done = target;
msh2_cycles = 0;
}
else if (msh2_cycles > 0) {
done = sh2_execute(&msh2, msh2_cycles);
msh2.m68krcycles_done += C_SH2_TO_M68K(msh2, done);
msh2_cycles = C_M68K_TO_SH2(msh2, target - msh2.m68krcycles_done);
}
}
}
}
#define STEP_68K 24
#define CPUS_RUN_LOCKSTEP(m68k_cycles,s68k_cycles) \
{ \
int slice; \
SekCycleAim += m68k_cycles; \
while (SekCycleCnt < SekCycleAim) { \
slice = SekCycleCnt; \
run_m68k(STEP_68K); \
if (!(Pico32x.regs[0] & P32XS_nRES)) \
continue; /* SH2s reseting */ \
slice = SekCycleCnt - slice; /* real count from 68k */ \
if (!(Pico32x.emu_flags & (P32XF_SSH2POLL|P32XF_SSH2VPOLL))) { \
sh2_execute(&ssh2, CYCLES_M68K2SSH2(slice)); \
} \
if (!(Pico32x.emu_flags & (P32XF_MSH2POLL|P32XF_MSH2VPOLL))) { \
sh2_execute(&msh2, CYCLES_M68K2MSH2(slice)); \
} \
} \
void sync_sh2s_lockstep(unsigned int m68k_target)
{
unsigned int mcycles;
mcycles = msh2.m68krcycles_done;
if (ssh2.m68krcycles_done < mcycles)
mcycles = ssh2.m68krcycles_done;
while (mcycles < m68k_target) {
mcycles += STEP_68K;
sync_sh2s_normal(mcycles);
}
}
#define CPUS_RUN CPUS_RUN_SIMPLE
//#define CPUS_RUN CPUS_RUN_LOCKSTEP
#define CPUS_RUN(m68k_cycles,s68k_cycles) do { \
SekRunM68k(m68k_cycles); \
if (SekIsStoppedM68k()) \
p32x_sync_sh2s(SekCycleCntT + SekCycleCnt); \
} while (0)
#define PICO_32X
#include "../pico_cmn.c"
void PicoFrame32x(void)
@ -291,3 +292,20 @@ void PicoFrame32x(void)
elprintf(EL_32X, "poll: %02x", Pico32x.emu_flags);
}
// calculate multipliers against 68k clock (7670442)
// normally * 3, but effectively slower due to high latencies everywhere
// however using something lower breaks MK2 animations
void Pico32xSetClocks(int msh2_hz, int ssh2_hz)
{
float m68k_clk = (float)(OSC_NTSC / 7);
if (msh2_hz > 0) {
msh2.mult_m68k_to_sh2 = (int)((float)msh2_hz * (1 << CYCLE_MULT_SHIFT) / m68k_clk);
msh2.mult_sh2_to_m68k = (int)(m68k_clk * (1 << CYCLE_MULT_SHIFT) / (float)msh2_hz);
}
if (ssh2_hz > 0) {
ssh2.mult_m68k_to_sh2 = (int)((float)ssh2_hz * (1 << CYCLE_MULT_SHIFT) / m68k_clk);
ssh2.mult_sh2_to_m68k = (int)(m68k_clk * (1 << CYCLE_MULT_SHIFT) / (float)ssh2_hz);
}
}
// vim:shiftwidth=2:ts=2:expandtab

View file

@ -1558,4 +1558,4 @@ void Pico32xStateLoaded(void)
#endif
}
// vim:shiftwidth=2:expandtab
// vim:shiftwidth=2:ts=2:expandtab

View file

@ -68,30 +68,6 @@ PICO_INTERNAL int PicoResetMCD(void)
return 0;
}
static __inline void SekRunM68k(int cyc)
{
int cyc_do;
pprof_start(m68k);
SekCycleAim+=cyc;
if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;
#if defined(EMU_CORE_DEBUG)
SekCycleCnt+=CM_compareRun(cyc_do, 0);
#elif defined(EMU_C68K)
PicoCpuCM68k.cycles=cyc_do;
CycloneRun(&PicoCpuCM68k);
SekCycleCnt+=cyc_do-PicoCpuCM68k.cycles;
#elif defined(EMU_M68K)
m68k_set_context(&PicoCpuMM68k);
SekCycleCnt+=m68k_execute(cyc_do);
#elif defined(EMU_F68K)
g_m68kcontext=&PicoCpuFM68k;
SekCycleCnt+=fm68k_emulate(cyc_do, 0, 0);
#endif
pprof_end(m68k);
}
static __inline void SekRunS68k(int cyc)
{
int cyc_do;
@ -106,9 +82,11 @@ static __inline void SekRunS68k(int cyc)
#elif defined(EMU_M68K)
m68k_set_context(&PicoCpuMS68k);
SekCycleCntS68k+=m68k_execute(cyc_do);
m68k_set_context(&PicoCpuMM68k);
#elif defined(EMU_F68K)
g_m68kcontext=&PicoCpuFS68k;
SekCycleCntS68k+=fm68k_emulate(cyc_do, 0, 0);
g_m68kcontext=&PicoCpuFM68k;
#endif
}

View file

@ -23,9 +23,6 @@ struct PicoSRAM SRam;
int emustatus; // rapid_ym2612, multi_ym_updates
int scanlines_total;
int p32x_msh2_multiplier = MSH2_MULTI_DEFAULT;
int p32x_ssh2_multiplier = SSH2_MULTI_DEFAULT;
void (*PicoWriteSound)(int len) = NULL; // called at the best time to send sound buffer (PsndOut) to hardware
void (*PicoResetHook)(void) = NULL;
void (*PicoLineHook)(void) = NULL;
@ -273,29 +270,6 @@ PICO_INTERNAL int CheckDMA(void)
return burn;
}
static __inline void SekRunM68k(int cyc)
{
int cyc_do;
pprof_start(m68k);
SekCycleAim+=cyc;
if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;
#if defined(EMU_CORE_DEBUG)
// this means we do run-compare
SekCycleCnt+=CM_compareRun(cyc_do, 0);
#elif defined(EMU_C68K)
PicoCpuCM68k.cycles=cyc_do;
CycloneRun(&PicoCpuCM68k);
SekCycleCnt+=cyc_do-PicoCpuCM68k.cycles;
#elif defined(EMU_M68K)
SekCycleCnt+=m68k_execute(cyc_do);
#elif defined(EMU_F68K)
SekCycleCnt+=fm68k_emulate(cyc_do+1, 0, 0);
#endif
pprof_end(m68k);
}
#include "pico_cmn.c"
int z80stopCycle;

View file

@ -212,18 +212,24 @@ extern unsigned short *PicoCramHigh; // pointer to CRAM buff (0x40 shorts), conv
extern void (*PicoPrepareCram)(); // prepares PicoCramHigh for renderer to use
// pico.c (32x)
// multipliers against 68k clock (7670442)
// normally * 3, but effectively slower due to high latencies everywhere
// however using something lower breaks MK2 animations
extern int p32x_msh2_multiplier;
extern int p32x_ssh2_multiplier;
#define SH2_MULTI_SHIFT 10
#define MSH2_MULTI_DEFAULT ((1 << SH2_MULTI_SHIFT) * 3)
#define SSH2_MULTI_DEFAULT ((1 << SH2_MULTI_SHIFT) * 3)
#ifndef NO_32X
void Pico32xSetClocks(int msh2_hz, int ssh2_hz);
// 32x/draw.c
void PicoDraw32xSetFrameMode(int is_on, int only_32x);
#else
#define Pico32xSetClocks(msh2_khz, ssh2_khz)
#endif
// normally 68k clock (7670442) * 3, in reality but much lower
// because of high memory latencies
#define PICO_MSH2_HZ ((int)(7670442.0 * 2.4))
#define PICO_SSH2_HZ ((int)(7670442.0 * 2.4))
// sound.c
extern int PsndRate,PsndLen;
extern short *PsndOut;

View file

@ -26,6 +26,29 @@
SekRunM68k(m68k_cycles)
#endif
static __inline void SekRunM68k(int cyc)
{
int cyc_do;
pprof_start(m68k);
SekCycleAim+=cyc;
if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;
#if defined(EMU_CORE_DEBUG)
// this means we do run-compare
SekCycleCnt+=CM_compareRun(cyc_do, 0);
#elif defined(EMU_C68K)
PicoCpuCM68k.cycles=cyc_do;
CycloneRun(&PicoCpuCM68k);
SekCycleCnt+=cyc_do-PicoCpuCM68k.cycles;
#elif defined(EMU_M68K)
SekCycleCnt+=m68k_execute(cyc_do);
#elif defined(EMU_F68K)
SekCycleCnt+=fm68k_emulate(cyc_do+1, 0, 0);
#endif
pprof_end(m68k);
}
static int PicoFrameHints(void)
{
struct PicoVideo *pv=&Pico.video;

View file

@ -50,6 +50,7 @@ extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k;
#define SekSr CycloneGetSr(&PicoCpuCM68k)
#define SekSetStop(x) { PicoCpuCM68k.state_flags&=~1; if (x) { PicoCpuCM68k.state_flags|=1; PicoCpuCM68k.cycles=0; } }
#define SekSetStopS68k(x) { PicoCpuCS68k.state_flags&=~1; if (x) { PicoCpuCS68k.state_flags|=1; PicoCpuCS68k.cycles=0; } }
#define SekIsStoppedM68k() (PicoCpuCM68k.state_flags&1)
#define SekIsStoppedS68k() (PicoCpuCS68k.state_flags&1)
#define SekShouldInterrupt (PicoCpuCM68k.irq > (PicoCpuCM68k.srh&7))
@ -83,6 +84,7 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k;
PicoCpuFS68k.execinfo &= ~FM68K_HALTED; \
if (x) { PicoCpuFS68k.execinfo |= FM68K_HALTED; PicoCpuFS68k.io_cycle_counter = 0; } \
}
#define SekIsStoppedM68k() (PicoCpuFM68k.execinfo&FM68K_HALTED)
#define SekIsStoppedS68k() (PicoCpuFS68k.execinfo&FM68K_HALTED)
#define SekShouldInterrupt fm68k_would_interrupt()
@ -117,6 +119,7 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k;
if(x) { SET_CYCLES(0); PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \
else PicoCpuMS68k.stopped=0; \
}
#define SekIsStoppedM68k() (PicoCpuMM68k.stopped==STOP_LEVEL_STOP)
#define SekIsStoppedS68k() (PicoCpuMS68k.stopped==STOP_LEVEL_STOP)
#define SekShouldInterrupt (CPU_INT_LEVEL > FLAG_INT_MASK)
@ -235,13 +238,13 @@ extern SH2 sh2s[2];
#ifndef DRC_SH2
# define ash2_end_run(after) if (sh2->icount > (after)) sh2->icount = after
# define ash2_cycles_done() (sh2->cycles_aim - sh2->icount)
# define ash2_cycles_done() (sh2->cycles_timeslice - sh2->icount)
#else
# define ash2_end_run(after) { \
if ((sh2->sr >> 12) > (after)) \
{ sh2->sr &= 0xfff; sh2->sr |= (after) << 12; } \
}
# define ash2_cycles_done() (sh2->cycles_aim - (sh2->sr >> 12))
# define ash2_cycles_done() (sh2->cycles_timeslice - (sh2->sr >> 12))
#endif
//#define sh2_pc(c) (c) ? ssh2.ppc : msh2.ppc
@ -712,6 +715,7 @@ void PicoReset32x(void);
void Pico32xStartup(void);
void PicoUnload32x(void);
void PicoFrame32x(void);
void p32x_sync_sh2s(unsigned int m68k_target);
void p32x_update_irls(int nested_call);
void p32x_reset_sh2s(void);

View file

@ -333,6 +333,8 @@ static int state_save(void *file)
CHECKED_WRITE_BUFF(CHUNK_SDRAM, Pico32xMem->sdram);
CHECKED_WRITE_BUFF(CHUNK_DRAM, Pico32xMem->dram);
CHECKED_WRITE_BUFF(CHUNK_32XPAL, Pico32xMem->pal);
sh2s[0].m68krcycles_done = sh2s[1].m68krcycles_done = SekCycleCnt;
}
#endif
@ -690,4 +692,4 @@ void PicoTmpStateRestore(void *data)
#endif
}
// vim:shiftwidth=2:expandtab
// vim:shiftwidth=2:ts=2:expandtab