fix sh4 scheduler. use common cycle counter in sh4 context

scheduler reset and unregister
schedule requests during reset(), not init()
preserve cntx.sh4_sched_next on sh4 reset
Use cntx.cycle_counter in dynarecs and interpreter
Fixes Confidential Mission hang at boot with HLE
This commit is contained in:
Flyinghead 2021-10-07 16:18:32 +02:00
parent bc238de5ce
commit bc3be1029c
24 changed files with 199 additions and 154 deletions

View File

@ -301,6 +301,7 @@ void dc_reset(bool hard)
NetworkHandshake::term();
if (hard)
_vmem_unprotect_vram(0, VRAM_SIZE);
sh4_sched_reset(hard);
libPvr_Reset(hard);
libAICA_Reset(hard);
libARM_Reset(hard);
@ -531,13 +532,13 @@ void Emulator::term()
debugger::term();
sh4_cpu.Term();
custom_texture.Terminate(); // lr: avoid deadlock on exit (win32)
reios_term();
libARM_Term();
libAICA_Term();
libPvr_Term();
mem_Term();
_vmem_release();
mcfg_DestroyDevices();
_vmem_release();
state = Terminated;
}
}
@ -633,7 +634,6 @@ bool dc_loadstate(const void **data, u32 size)
mmu_set_state();
sh4_cpu.ResetCache();
sh4_sched_ffts();
return true;
}

View File

@ -258,10 +258,7 @@ s32 libAICA_Init()
sgc_Init();
if (aica_schid == -1)
{
aica_schid = sh4_sched_register(0, &AicaUpdate);
sh4_sched_request(aica_schid, AICA_TICK);
}
return 0;
}
@ -272,6 +269,7 @@ void libAICA_Reset(bool hard)
{
init_mem();
sgc_Init();
sh4_sched_request(aica_schid, AICA_TICK);
}
for (u32 i = 0; i < 3; i++)
timers[i].Init(aica_reg, i);
@ -282,4 +280,6 @@ void libAICA_Term()
{
sgc_Term();
term_mem();
sh4_sched_unregister(aica_schid);
aica_schid = -1;
}

View File

@ -20,7 +20,7 @@ VArray2 aica_ram;
u32 VREG;
u32 ARMRST;
u32 rtc_EN;
int dma_sched_id;
int dma_sched_id = -1;
u32 RealTimeClock;
int rtc_schid = -1;
u32 SB_ADST;
@ -168,23 +168,24 @@ void aica_Init()
{
RealTimeClock = GetRTC_now();
if (rtc_schid == -1)
{
rtc_schid = sh4_sched_register(0, &DreamcastSecond);
sh4_sched_request(rtc_schid, SH4_MAIN_CLOCK);
}
}
void aica_Reset(bool hard)
{
if (hard)
{
aica_Init();
sh4_sched_request(rtc_schid, SH4_MAIN_CLOCK);
}
VREG = 0;
ARMRST = 0;
}
void aica_Term()
{
sh4_sched_unregister(rtc_schid);
rtc_schid = -1;
}
static int dma_end_sched(int tag, int cycl, int jitt)
@ -475,4 +476,6 @@ void aica_sb_Reset(bool hard)
void aica_sb_Term()
{
sh4_sched_unregister(dma_sched_id);
dma_sched_id = -1;
}

View File

@ -1201,7 +1201,8 @@ void gdrom_reg_Init()
void gdrom_reg_Term()
{
sh4_sched_unregister(gdrom_schid);
gdrom_schid = -1;
}
void gdrom_reg_Reset(bool hard)

View File

@ -597,7 +597,7 @@ void sb_Reset(bool hard)
SB_FFST = 0;
bba_Reset(hard);
ModemTerm();
ModemReset();
asic_reg_Reset(hard);
if (settings.platform.system == DC_PLATFORM_DREAMCAST)

View File

@ -333,7 +333,9 @@ void maple_Reset(bool hard)
void maple_Term()
{
mcfg_DestroyDevices();
sh4_sched_unregister(maple_schid);
maple_schid = -1;
}
static u64 reconnect_time;

View File

@ -331,11 +331,6 @@ void _vmem_mirror_mapping(u32 new_region,u32 start,u32 size)
//init/reset/term
void _vmem_init()
{
_vmem_reset();
}
void _vmem_reset()
{
//clear read tables
memset(_vmem_RF8,0,sizeof(_vmem_RF8));
@ -363,7 +358,7 @@ void _vmem_term()
u8* virt_ram_base;
bool vmem_4gb_space;
static VMemType vmemstatus;
static VMemType vmemstatus = MemTypeError;
static void* malloc_pages(size_t size) {
#ifdef _WIN32
@ -441,7 +436,8 @@ bool _vmem_reserve()
{
static_assert((sizeof(Sh4RCB) % PAGE_SIZE) == 0, "sizeof(Sh4RCB) not multiple of PAGE_SIZE");
vmemstatus = MemTypeError;
if (vmemstatus != MemTypeError)
return true;
// Use vmem only if settings mandate so, and if we have proper exception handlers.
#if !defined(TARGET_NO_EXCEPTIONS)
@ -595,16 +591,22 @@ void _vmem_init_mappings()
#define freedefptr(x) \
if (x) { free(x); x = NULL; }
void _vmem_release() {
void _vmem_release()
{
if (virt_ram_base)
{
vmem_platform_destroy();
else {
virt_ram_base = nullptr;
}
else
{
_vmem_unprotect_vram(0, VRAM_SIZE);
freedefptr(p_sh4rcb);
freedefptr(vram.data);
freedefptr(aica_ram.data);
freedefptr(mem_b.data);
}
vmemstatus = MemTypeError;
}
void _vmem_protect_vram(u32 addr, u32 size)

View File

@ -53,7 +53,6 @@ typedef u32 _vmem_handler;
//init/reset/term
void _vmem_init();
void _vmem_reset();
void _vmem_term();
void _vmem_init_mappings();

View File

@ -319,11 +319,18 @@ void ModemInit()
modem_sched = sh4_sched_register(0, &modem_sched_func);
}
void ModemTerm()
void ModemReset()
{
stop_pico();
}
void ModemTerm()
{
ModemReset();
sh4_sched_unregister(modem_sched);
modem_sched = -1;
}
static void schedule_callback(int ms)
{
sh4_sched_request(modem_sched, SH4_MAIN_CLOCK / 1000 * ms);

View File

@ -25,6 +25,7 @@
#include "types.h"
void ModemInit();
void ModemReset();
void ModemTerm();
u32 ModemReadMem_A0_006(u32 addr,u32 size);
void ModemWriteMem_A0_006(u32 addr,u32 data,u32 size);

View File

@ -74,6 +74,7 @@ void CalculateSync()
Frame_Cycles = pvr_numscanlines * Line_Cycles;
prv_cur_scanline = 0;
clc_pvr_scanline = 0;
sh4_sched_request(vblank_schid, Line_Cycles);
}
@ -293,6 +294,10 @@ bool spg_Init()
void spg_Term()
{
sh4_sched_unregister(render_end_schid);
render_end_schid = -1;
sh4_sched_unregister(vblank_schid);
vblank_schid = -1;
}
void spg_Reset(bool hard)

View File

@ -19,14 +19,12 @@
sh4_icache icache;
sh4_ocache ocache;
s32 sh4InterpCycles;
static void ExecuteOpcode(u16 op)
{
if (sr.FD == 1 && OpDesc[op]->IsFloatingPoint())
RaiseFPUDisableException();
OpPtr[op](op);
sh4InterpCycles -= CPU_RATIO;
p_sh4rcb->cntx.cycle_counter -= CPU_RATIO;
}
static u16 ReadNexOp()
@ -42,8 +40,6 @@ static void Sh4_int_Run()
sh4_int_bCpuRun = true;
RestoreHostRoundingMode();
sh4InterpCycles += SH4_TIMESLICE;
try {
do
{
@ -53,12 +49,12 @@ static void Sh4_int_Run()
u32 op = ReadNexOp();
ExecuteOpcode(op);
} while (sh4InterpCycles > 0);
sh4InterpCycles += SH4_TIMESLICE;
} while (p_sh4rcb->cntx.cycle_counter > 0);
p_sh4rcb->cntx.cycle_counter += SH4_TIMESLICE;
UpdateSystem_INTC();
} catch (const SH4ThrownException& ex) {
Do_Exception(ex.epc, ex.expEvn, ex.callVect);
sh4InterpCycles -= CPU_RATIO * 5; // an exception requires the instruction pipeline to drain, so approx 5 cycles
p_sh4rcb->cntx.cycle_counter -= CPU_RATIO * 5; // an exception requires the instruction pipeline to drain, so approx 5 cycles
}
} while (sh4_int_bCpuRun);
} catch (const debugger::Stop& e) {
@ -82,7 +78,7 @@ static void Sh4_int_Step()
ExecuteOpcode(op);
} catch (const SH4ThrownException& ex) {
Do_Exception(ex.epc, ex.expEvn, ex.callVect);
sh4InterpCycles -= CPU_RATIO * 5; // an exception requires the instruction pipeline to drain, so approx 5 cycles
p_sh4rcb->cntx.cycle_counter -= CPU_RATIO * 5; // an exception requires the instruction pipeline to drain, so approx 5 cycles
} catch (const debugger::Stop& e) {
}
}
@ -92,7 +88,11 @@ static void Sh4_int_Reset(bool hard)
verify(!sh4_int_bCpuRun);
if (hard)
{
int schedNext = p_sh4rcb->cntx.sh4_sched_next;
memset(&p_sh4rcb->cntx, 0, sizeof(p_sh4rcb->cntx));
p_sh4rcb->cntx.sh4_sched_next = schedNext;
}
next_pc = 0xA0000000;
memset(r,0,sizeof(r));
@ -110,7 +110,7 @@ static void Sh4_int_Reset(bool hard)
UpdateFPSCR();
icache.Reset(hard);
ocache.Reset(hard);
sh4InterpCycles = 0;
p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE;
INFO_LOG(INTERPRETER, "Sh4 Reset");
}

View File

@ -322,4 +322,9 @@ void tmu_reset(bool hard)
void tmu_term()
{
for (int& sched_id : tmu_sched)
{
sh4_sched_unregister(sched_id);
sched_id = -1;
}
}

View File

@ -269,6 +269,7 @@ struct alignas(64) Sh4Context
u32 interrupt_pend;
u32 temp_reg;
int cycle_counter;
};
u64 raw[64-8];
};

View File

@ -45,5 +45,3 @@ void ExecuteDelayslot_RTE();
int UpdateSystem();
int UpdateSystem_INTC();
extern s32 sh4InterpCycles;

View File

@ -18,66 +18,84 @@
sh4_sched_now()
*/
u64 sh4_sched_ffb;
std::vector<sched_list> sch_list;
int sh4_sched_next_id = -1;
static u32 sh4_sched_now();
std::vector<sched_list> sch_list; // using list as external inside a macro confuses clang and msc
int sh4_sched_next_id=-1;
u32 sh4_sched_remaining(size_t id, u32 reference)
static u32 sh4_sched_remaining(const sched_list& sched, u32 reference)
{
if (sch_list[id].end != -1)
return sch_list[id].end - reference;
if (sched.end != -1)
return sched.end - reference;
else
return -1;
}
u32 sh4_sched_remaining(size_t id)
{
return sh4_sched_remaining(id, sh4_sched_now());
}
void sh4_sched_ffts()
{
u32 diff=-1;
int slot=-1;
u32 diff = -1;
int slot = -1;
for (size_t i=0;i<sch_list.size();i++)
u32 now = sh4_sched_now();
for (const sched_list& sched : sch_list)
{
if (sh4_sched_remaining(i)<diff)
u32 remaining = sh4_sched_remaining(sched, now);
if (remaining < diff)
{
slot=i;
diff=sh4_sched_remaining(i);
slot = &sched - &sch_list[0];
diff = remaining;
}
}
sh4_sched_ffb-=Sh4cntx.sh4_sched_next;
sh4_sched_ffb -= Sh4cntx.sh4_sched_next;
sh4_sched_next_id=slot;
if (slot!=-1)
Sh4cntx.sh4_sched_next=diff;
sh4_sched_next_id = slot;
if (slot != -1)
Sh4cntx.sh4_sched_next = diff;
else
Sh4cntx.sh4_sched_next=SH4_MAIN_CLOCK;
Sh4cntx.sh4_sched_next = SH4_MAIN_CLOCK;
sh4_sched_ffb+=Sh4cntx.sh4_sched_next;
sh4_sched_ffb += Sh4cntx.sh4_sched_next;
}
int sh4_sched_register(int tag, sh4_sched_callback* ssc)
{
sched_list t={ssc,tag,-1,-1};
sched_list t{ ssc, tag, -1, -1};
for (sched_list& sched : sch_list)
if (sched.cb == nullptr)
{
sched = t;
return &sched - &sch_list[0];
}
sch_list.push_back(t);
return sch_list.size()-1;
return sch_list.size() - 1;
}
void sh4_sched_unregister(int id)
{
if (id == -1)
return;
verify(id < (int)sch_list.size());
if (id == (int)sch_list.size() - 1)
sch_list.resize(sch_list.size() - 1);
else
{
sch_list[id].cb = nullptr;
sch_list[id].end = -1;
}
sh4_sched_ffts();
}
/*
Return current cycle count, in 32 bits (wraps after 21 dreamcast seconds)
*/
u32 sh4_sched_now()
static u32 sh4_sched_now()
{
return sh4_sched_ffb-Sh4cntx.sh4_sched_next;
return sh4_sched_ffb - Sh4cntx.sh4_sched_next;
}
/*
@ -85,74 +103,83 @@ u32 sh4_sched_now()
*/
u64 sh4_sched_now64()
{
return sh4_sched_ffb-Sh4cntx.sh4_sched_next;
return sh4_sched_ffb - Sh4cntx.sh4_sched_next;
}
void sh4_sched_request(size_t id, int cycles)
{
verify(cycles== -1 || (cycles >= 0 && cycles <= SH4_MAIN_CLOCK));
sch_list[id].start=sh4_sched_now();
void sh4_sched_request(int id, int cycles)
{
verify(cycles == -1 || (cycles >= 0 && cycles <= SH4_MAIN_CLOCK));
sched_list& sched = sch_list[id];
sched.start = sh4_sched_now();
if (cycles == -1)
{
sch_list[id].end = -1;
sched.end = -1;
}
else
{
sch_list[id].end = sch_list[id].start + cycles;
if (sch_list[id].end == -1)
sch_list[id].end++;
sched.end = sched.start + cycles;
if (sched.end == -1)
sched.end++;
}
sh4_sched_ffts();
}
/* Returns how much time has passed for this callback */
static int sh4_sched_elapsed(size_t id)
static int sh4_sched_elapsed(sched_list& sched)
{
if (sch_list[id].end!=-1)
if (sched.end != -1)
{
int rv=sh4_sched_now()-sch_list[id].start;
sch_list[id].start=sh4_sched_now();
int rv = sh4_sched_now() - sched.start;
sched.start = sh4_sched_now();
return rv;
}
else
return -1;
}
static void handle_cb(size_t id)
static void handle_cb(sched_list& sched)
{
int remain=sch_list[id].end-sch_list[id].start;
int elapsd=sh4_sched_elapsed(id);
int jitter=elapsd-remain;
int remain = sched.end - sched.start;
int elapsd = sh4_sched_elapsed(sched);
int jitter = elapsd - remain;
sch_list[id].end=-1;
int re_sch=sch_list[id].cb(sch_list[id].tag,remain,jitter);
sched.end = -1;
int re_sch = sched.cb(sched.tag, remain, jitter);
if (re_sch > 0)
sh4_sched_request(id, std::max(0, re_sch - jitter));
sh4_sched_request(&sched - &sch_list[0], std::max(0, re_sch - jitter));
}
void sh4_sched_tick(int cycles)
{
/*
Sh4cntx.sh4_sched_time+=cycles;
Sh4cntx.sh4_sched_next-=cycles;
*/
if (Sh4cntx.sh4_sched_next >= 0)
return;
if (Sh4cntx.sh4_sched_next<0)
u32 fztime = sh4_sched_now() - cycles;
if (sh4_sched_next_id != -1)
{
u32 fztime=sh4_sched_now()-cycles;
if (sh4_sched_next_id!=-1)
for (sched_list& sched : sch_list)
{
for (size_t i = 0; i < sch_list.size(); i++)
{
u32 remaining = sh4_sched_remaining(i, fztime);
verify(remaining >= 0 || remaining == -1);
if (remaining >= 0 && remaining <= (u32)cycles)
handle_cb(i);
}
int remaining = sh4_sched_remaining(sched, fztime);
verify(remaining >= 0 || remaining == -1);
if (remaining >= 0 && remaining <= (int)cycles)
handle_cb(sched);
}
sh4_sched_ffts();
}
sh4_sched_ffts();
}
void sh4_sched_reset(bool hard)
{
if (hard)
{
sh4_sched_ffb = 0;
sh4_sched_next_id = -1;
for (sched_list& sched : sch_list)
sched.start = sched.end = -1;
Sh4cntx.sh4_sched_next = 0;
}
}

View File

@ -11,16 +11,15 @@
typedef int sh4_sched_callback(int tag, int sch_cycl, int jitter);
/*
Registed a callback to the scheduler. The returned id
is used for sh4_sched_request and sh4_sched_elapsed calls
Register a callback to the scheduler. The returned id
is used for sh4_sched_request and sh4_sched_unregister calls
*/
int sh4_sched_register(int tag, sh4_sched_callback* ssc);
/*
current time in SH4 cycles, referenced to boot.
Wraps every ~21 secs
*/
u32 sh4_sched_now();
/***
* Unregister a callback from the scheduler.
*/
void sh4_sched_unregister(int id);
/*
current time, in SH4 cycles, referenced to boot.
@ -35,7 +34,7 @@ u64 sh4_sched_now64();
Passing a value of 0 disables the callback.
If called multiple times, only the last call is in effect
*/
void sh4_sched_request(size_t id, int cycles);
void sh4_sched_request(int id, int cycles);
/*
Tick for *cycles*
@ -43,6 +42,7 @@ void sh4_sched_request(size_t id, int cycles);
void sh4_sched_tick(int cycles);
void sh4_sched_ffts();
void sh4_sched_reset(bool hard);
struct sched_list
{

View File

@ -2046,9 +2046,9 @@ void ngen_Compile(RuntimeBlockInfo* block, bool force_checks, bool reset, bool s
}
else
{
ass.Ldr(r0, MemOperand(sp));
ass.Ldr(r0, MemOperand(r8, rcbOffset(cntx.cycle_counter)));
ass.Sub(SetFlags, r0, r0, cyc);
ass.Str(r0, MemOperand(sp));
ass.Str(r0, MemOperand(r8, rcbOffset(cntx.cycle_counter)));
// FIXME condition?
ass.Mov(r4, block->vaddr);
storeSh4Reg(r4, reg_nextpc);
@ -2184,14 +2184,15 @@ static void generate_mainloop()
Label longjumpLabel;
if (!mmu_enabled())
{
ass.Mov(r8, r0); // r8: context
ass.Mov(r9, SH4_TIMESLICE); // r9: cycle counter
// r8: context
ass.Mov(r8, r0);
// r9: cycle counter
ass.Ldr(r9, MemOperand(r0, rcbOffset(cntx.cycle_counter)));
}
else
{
ass.Sub(sp, sp, 4);
ass.Push(r0); // push context
ass.Mov(r1, SH4_TIMESLICE);
ass.Push(r1); // cycle counter on stack
ass.Mov(r0, reinterpret_cast<uintptr_t>(&jmp_stack));
ass.Mov(r1, sp);
@ -2199,7 +2200,7 @@ static void generate_mainloop()
ass.Bind(&longjumpLabel);
ass.Ldr(r8, MemOperand(sp, 4)); // r8: context
ass.Ldr(r8, MemOperand(sp)); // r8: context
ass.Mov(r9, (uintptr_t)mmuAddressLUT); // r9: mmu LUT
}
ass.Ldr(r4, MemOperand(r8, rcbOffset(cntx.pc))); // r4: pc
@ -2213,9 +2214,9 @@ static void generate_mainloop()
ass.Add(r9, r9, SH4_TIMESLICE);
else
{
ass.Ldr(r0, MemOperand(sp));
ass.Ldr(r0, MemOperand(r8, rcbOffset(cntx.cycle_counter)));
ass.Add(r0, r0, SH4_TIMESLICE);
ass.Str(r0, MemOperand(sp));
ass.Str(r0, MemOperand(r8, rcbOffset(cntx.cycle_counter)));
}
ass.Mov(r4, lr);
call((void *)UpdateSystem);
@ -2256,7 +2257,9 @@ static void generate_mainloop()
// cleanup:
ass.Bind(&cleanup);
if (mmu_enabled())
ass.Add(sp, sp, 8); // pop cycle counter & context
ass.Add(sp, sp, 8); // pop context & alignment
else
ass.Str(r9, MemOperand(r8, rcbOffset(cntx.cycle_counter)));
{
UseScratchRegisterScope scope(&ass);
scope.ExcludeAll();

View File

@ -300,10 +300,9 @@ public:
// scheduler
if (mmu_enabled())
{
Mov(x1, reinterpret_cast<uintptr_t>(&cycle_counter));
Ldr(w0, MemOperand(x1));
Ldr(w0, sh4_context_mem_operand(&Sh4cntx.cycle_counter));
Subs(w0, w0, block->guest_cycles);
Str(w0, MemOperand(x1));
Str(w0, sh4_context_mem_operand(&Sh4cntx.cycle_counter));
}
else
{
@ -1390,12 +1389,9 @@ public:
Label reenterLabel;
if (mmu_enabled())
{
Ldr(x1, reinterpret_cast<uintptr_t>(&cycle_counter));
// Push context, cycle_counter address
// Push context
Stp(x0, x1, MemOperand(sp, -16, PreIndex));
unwinder.allocStack(0, 16);
Mov(w0, SH4_TIMESLICE);
Str(w0, MemOperand(x1));
Ldr(x0, reinterpret_cast<uintptr_t>(&jmp_stack));
Mov(x1, sp);
@ -1410,7 +1406,7 @@ public:
// Use x28 as sh4 context pointer
Mov(x28, x0);
// Use x27 as cycle_counter
Mov(w27, SH4_TIMESLICE);
Ldr(w27, sh4_context_mem_operand(&Sh4cntx.cycle_counter));
}
Label do_interrupts;
@ -1427,10 +1423,9 @@ public:
}
else
{
Ldr(x1, MemOperand(sp, 8)); // &cycle_counter
Ldr(w0, MemOperand(x1)); // cycle_counter
Ldr(w0, sh4_context_mem_operand(&Sh4cntx.cycle_counter));
Add(w0, w0, SH4_TIMESLICE);
Str(w0, MemOperand(x1));
Str(w0, sh4_context_mem_operand(&Sh4cntx.cycle_counter));
}
Mov(x29, lr); // Trashing pc here but it will be reset at the end of the block or in DoInterrupts
GenCallRuntime(UpdateSystem);
@ -1450,6 +1445,9 @@ public:
if (mmu_enabled())
// Pop context
Add(sp, sp, 16);
else
// save cycle counter
Str(w27, sh4_context_mem_operand(&Sh4cntx.cycle_counter));
// Restore registers
Ldp(x29, x30, MemOperand(sp, 144));
Ldp(d12, d13, MemOperand(sp, 128));

View File

@ -32,7 +32,6 @@ struct DynaRBI : RuntimeBlockInfo
}
};
static int cycle_counter;
static void (*mainloop)();
static void (*handleException)();
@ -106,7 +105,7 @@ static void handle_sh4_exception(SH4ThrownException& ex, u32 pc)
pc--;
}
Do_Exception(pc, ex.expEvn, ex.callVect);
cycle_counter += 4; // probably more is needed
p_sh4rcb->cntx.cycle_counter += 4; // probably more is needed
handleException();
}
@ -176,14 +175,9 @@ public:
jmp(exit_block, T_NEAR);
L(fpu_enabled);
}
#ifdef FEAT_NO_RWX_PAGES
// Use absolute addressing for this one
// TODO(davidgfnet) remove the ifsef using CC_RX2RW/CC_RW2RX
mov(rax, (uintptr_t)&cycle_counter);
mov(rax, (uintptr_t)&p_sh4rcb->cntx.cycle_counter);
sub(dword[rax], block->guest_cycles);
#else
sub(dword[rip + &cycle_counter], block->guest_cycles);
#endif
regalloc.DoAlloc(block);
for (current_opid = 0; current_opid < block->oplist.size(); current_opid++)
@ -655,7 +649,6 @@ public:
#endif
unwinder.endProlog(getSize());
mov(dword[rip + &cycle_counter], SH4_TIMESLICE);
mov(qword[rip + &jmp_rsp], rsp);
//run_loop:
@ -675,12 +668,13 @@ public:
mov(call_regs[0], dword[rax]);
call(bm_GetCodeByVAddr);
call(rax);
mov(ecx, dword[rip + &cycle_counter]);
mov(rax, (uintptr_t)&p_sh4rcb->cntx.cycle_counter);
mov(ecx, dword[rax]);
test(ecx, ecx);
jg(slice_loop);
add(ecx, SH4_TIMESLICE);
mov(dword[rip + &cycle_counter], ecx);
mov(dword[rax], ecx);
call(UpdateSystem_INTC);
jmp(run_loop);

View File

@ -28,7 +28,6 @@
#include "hw/mem/_vmem.h"
#include "oslib/oslib.h"
static int cycle_counter;
static void (*mainloop)();
static void (*ngen_FailedToFindBlock_)();
@ -110,7 +109,7 @@ void X86Compiler::compile(RuntimeBlockInfo* block, bool force_checks, bool optim
checkBlock(force_checks, block);
sub(dword[&cycle_counter], block->guest_cycles);
sub(dword[&Sh4cntx.cycle_counter], block->guest_cycles);
Xbyak::Label no_up;
jns(no_up);
call((const void *)intc_sched);
@ -396,8 +395,6 @@ void X86Compiler::genMainloop()
mov(ecx, dword[&Sh4cntx.pc]);
mov(dword[&cycle_counter], SH4_TIMESLICE);
mov(eax, 0);
//next_pc _MUST_ be on ecx
Xbyak::Label cleanup;
@ -452,7 +449,7 @@ void X86Compiler::genMainloop()
unwinder.endProlog(0);
Xbyak::Label intc_schedLabel;
L(intc_schedLabel);
add(dword[&cycle_counter], SH4_TIMESLICE);
add(dword[&Sh4cntx.cycle_counter], SH4_TIMESLICE);
call((void *)UpdateSystem);
cmp(eax, 0);
jnz(do_iter);

View File

@ -392,7 +392,6 @@ bool dc_serialize(void **data, unsigned int *total_size, bool rollback)
REICAST_S((*p_sh4rcb).cntx);
REICAST_S(sh4InterpCycles);
REICAST_S(sh4_sched_ffb);
std::array<int, 11> schedIds = getSchedulerIds();
if (sh4_sched_next_id == -1)
@ -693,6 +692,7 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size, seria
REICAST_US((*p_sh4rcb).sq_buffer);
REICAST_US((*p_sh4rcb).cntx);
p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE;
if (version < V9_LIBRETRO)
{
@ -700,7 +700,6 @@ static bool dc_unserialize_libretro(void **data, unsigned int *total_size, seria
REICAST_SKIP(4); // old_dn
}
sh4InterpCycles = 0;
REICAST_US(sh4_sched_ffb);
if (version < V9_LIBRETRO)
REICAST_SKIP(4); // sh4_sched_intr
@ -1080,10 +1079,10 @@ bool dc_unserialize(void **data, unsigned int *total_size, bool rollback)
REICAST_SKIP(4);
REICAST_SKIP(4);
}
if (version >= V19)
REICAST_US(sh4InterpCycles);
else
sh4InterpCycles = 0;
if (version >= V19 && version < V21)
REICAST_SKIP(4); // sh4InterpCycles
if (version < V21)
p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE;
REICAST_US(sh4_sched_ffb);
std::array<int, 11> schedIds = getSchedulerIds();
@ -1125,6 +1124,8 @@ bool dc_unserialize(void **data, unsigned int *total_size, bool rollback)
REICAST_US(sch_list[modem_sched].start);
REICAST_US(sch_list[modem_sched].end);
}
if (version < V19)
sh4_sched_ffts();
ModemDeserialize(data, total_size, version);
REICAST_US(SCIF_SCFSR2);

View File

@ -490,5 +490,6 @@ enum serialize_version_enum {
V18 = 813,
V19 = 814,
V20 = 815,
VCUR_FLYCAST = V20,
V21 = 816,
VCUR_FLYCAST = V21,
};

View File

@ -31,7 +31,7 @@ TEST_F(SerializeTest, SizeTest)
unsigned int total_size = 0;
void *data = nullptr;
ASSERT_TRUE(dc_serialize(&data, &total_size));
ASSERT_EQ(28192084u, total_size);
ASSERT_EQ(28192080u, total_size);
}