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:
parent
bc238de5ce
commit
bc3be1029c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -53,7 +53,6 @@ typedef u32 _vmem_handler;
|
|||
|
||||
//init/reset/term
|
||||
void _vmem_init();
|
||||
void _vmem_reset();
|
||||
void _vmem_term();
|
||||
void _vmem_init_mappings();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -269,6 +269,7 @@ struct alignas(64) Sh4Context
|
|||
u32 interrupt_pend;
|
||||
|
||||
u32 temp_reg;
|
||||
int cycle_counter;
|
||||
};
|
||||
u64 raw[64-8];
|
||||
};
|
||||
|
|
|
@ -45,5 +45,3 @@ void ExecuteDelayslot_RTE();
|
|||
|
||||
int UpdateSystem();
|
||||
int UpdateSystem_INTC();
|
||||
|
||||
extern s32 sh4InterpCycles;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -490,5 +490,6 @@ enum serialize_version_enum {
|
|||
V18 = 813,
|
||||
V19 = 814,
|
||||
V20 = 815,
|
||||
VCUR_FLYCAST = V20,
|
||||
V21 = 816,
|
||||
VCUR_FLYCAST = V21,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue