Revert the following commits, from newest to oldest, which all hacked around cothread savestates:
a60be7d2c9
a7b6a9af4d
57b1df8487
9119e4f4ea
b2c0910376
587270cad2
74c26d9b11
5e3d6555b0
451f786660
This commit is contained in:
parent
767ae4d8b9
commit
9ecf86a80a
|
@ -60,24 +60,19 @@ void CPU::enter() {
|
|||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if (regs.hang == HangType::Wait) this->op_wai();
|
||||
else if (regs.hang == HangType::Stop) this->op_stp();
|
||||
else
|
||||
{
|
||||
if(status.nmi_pending) {
|
||||
status.nmi_pending = false;
|
||||
regs.vector = (regs.e == false ? 0xffea : 0xfffa);
|
||||
op_irq();
|
||||
}
|
||||
if(status.nmi_pending) {
|
||||
status.nmi_pending = false;
|
||||
regs.vector = (regs.e == false ? 0xffea : 0xfffa);
|
||||
op_irq();
|
||||
}
|
||||
|
||||
if(status.irq_pending) {
|
||||
status.irq_pending = false;
|
||||
regs.vector = (regs.e == false ? 0xffee : 0xfffe);
|
||||
op_irq();
|
||||
}
|
||||
if(status.irq_pending) {
|
||||
status.irq_pending = false;
|
||||
regs.vector = (regs.e == false ? 0xffee : 0xfffe);
|
||||
op_irq();
|
||||
}
|
||||
|
||||
op_step();
|
||||
}
|
||||
op_step();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,7 @@ void PPU::step(unsigned clocks) {
|
|||
|
||||
void PPU::synchronize_cpu() {
|
||||
if(CPU::Threaded == true) {
|
||||
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All)
|
||||
co_switch(cpu.thread);
|
||||
else if(clock >= 0 && scheduler.sync == Scheduler::SynchronizeMode::All)
|
||||
interface()->message("PPU had to advance nondeterministically!");
|
||||
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
|
||||
} else {
|
||||
while(clock >= 0) cpu.enter();
|
||||
}
|
||||
|
@ -29,32 +26,14 @@ void PPU::Enter() { ppu.enter(); }
|
|||
|
||||
void PPU::enter() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
|
||||
synchronize_cpu(); // when in CPU sync mode, always switch back to CPU as soon as possible
|
||||
}
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
switch(uindex)
|
||||
{
|
||||
case 0: enter1(); break;
|
||||
case 1: enter2(); break;
|
||||
case 2: enter3(); break;
|
||||
case 3: enter4(); break;
|
||||
}
|
||||
uindex++;
|
||||
uindex &= 3;
|
||||
}
|
||||
}
|
||||
|
||||
void PPU::enter1() {
|
||||
//H = 0 (initialize)
|
||||
scanline();
|
||||
add_clocks(10);
|
||||
}
|
||||
|
||||
void PPU::enter2() {
|
||||
//H = 10 (cache mode7 registers + OAM address reset)
|
||||
cache.m7_hofs = regs.m7_hofs;
|
||||
cache.m7_vofs = regs.m7_vofs;
|
||||
|
@ -71,15 +50,11 @@ void PPU::enter2() {
|
|||
}
|
||||
}
|
||||
add_clocks(502);
|
||||
}
|
||||
|
||||
void PPU::enter3() {
|
||||
//H = 512 (render)
|
||||
render_scanline();
|
||||
add_clocks(640);
|
||||
}
|
||||
|
||||
void PPU::enter4() {
|
||||
//H = 1152 (cache OBSEL)
|
||||
if(cache.oam_basesize != regs.oam_basesize) {
|
||||
cache.oam_basesize = regs.oam_basesize;
|
||||
|
@ -88,6 +63,8 @@ void PPU::enter4() {
|
|||
cache.oam_nameselect = regs.oam_nameselect;
|
||||
cache.oam_tdaddr = regs.oam_tdaddr;
|
||||
add_clocks(lineclocks() - 1152); //seek to start of next scanline
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PPU::add_clocks(unsigned clocks) {
|
||||
|
@ -373,8 +350,6 @@ void PPU::reset() {
|
|||
PPUcounter::reset();
|
||||
memset(surface, 0, 512 * 512 * sizeof(uint32));
|
||||
|
||||
uindex = 0;
|
||||
|
||||
//zero 01-dec-2012 - gotta reset these sometime, somewhere
|
||||
memset(oam_itemlist, 0, sizeof(oam_itemlist));
|
||||
memset(oam_tilelist, 0, sizeof(oam_tilelist));
|
||||
|
|
|
@ -12,8 +12,6 @@ public:
|
|||
#include "mmio/mmio.hpp"
|
||||
#include "render/render.hpp"
|
||||
|
||||
int uindex;
|
||||
|
||||
uint32 *surface;
|
||||
uint32 *output;
|
||||
|
||||
|
@ -61,10 +59,6 @@ public:
|
|||
void render_scanline();
|
||||
void frame();
|
||||
void enter();
|
||||
void enter1();
|
||||
void enter2();
|
||||
void enter3();
|
||||
void enter4();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
|
|
@ -203,8 +203,6 @@ void PPU::serialize(serializer &s) {
|
|||
|
||||
s.array(oam_line_pal, 256);
|
||||
s.array(oam_line_pri, 256);
|
||||
|
||||
s.integer(uindex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,14 +17,10 @@ void HitachiDSP::Enter() { hitachidsp.enter(); }
|
|||
|
||||
void HitachiDSP::enter() {
|
||||
while(true) {
|
||||
// exit requested due to savestate
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
// if we bail out due to savestating, the first thing we'll try afterwards is synchronize_cpu() again
|
||||
synchronize_cpu();
|
||||
|
||||
switch(state) {
|
||||
case State::Idle:
|
||||
step(1);
|
||||
|
@ -46,8 +42,7 @@ void HitachiDSP::enter() {
|
|||
break;
|
||||
}
|
||||
|
||||
// this call is gone, but it's the first thing we try at the top of the loop AFTER we bail out
|
||||
//synchronize_cpu();
|
||||
synchronize_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,25 +19,20 @@ void SA1::enter() {
|
|||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if (regs.hang == HangType::Wait) this->op_wai();
|
||||
else if (regs.hang == HangType::Stop) this->op_stp();
|
||||
else
|
||||
{
|
||||
if(mmio.sa1_rdyb || mmio.sa1_resb) {
|
||||
//SA-1 co-processor is asleep
|
||||
tick();
|
||||
synchronize_cpu();
|
||||
continue;
|
||||
}
|
||||
if(mmio.sa1_rdyb || mmio.sa1_resb) {
|
||||
//SA-1 co-processor is asleep
|
||||
tick();
|
||||
synchronize_cpu();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(status.interrupt_pending) {
|
||||
status.interrupt_pending = false;
|
||||
op_irq();
|
||||
continue;
|
||||
}
|
||||
if(status.interrupt_pending) {
|
||||
status.interrupt_pending = false;
|
||||
op_irq();
|
||||
continue;
|
||||
}
|
||||
|
||||
(this->*opcode_table[op_readpc()])();
|
||||
}
|
||||
(this->*opcode_table[op_readpc()])();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,28 +72,16 @@ L rd.h = op_readlong(vectorN + 1);
|
|||
}
|
||||
|
||||
void CPUcore::op_stp() {
|
||||
if(regs.hang == HangType::Stop)
|
||||
goto SKIP;
|
||||
regs.hang = HangType::Stop;
|
||||
while(regs.wai = true) {
|
||||
L op_io();
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
SKIP: ;
|
||||
}
|
||||
regs.hang = HangType::None;
|
||||
}
|
||||
}
|
||||
|
||||
void CPUcore::op_wai() {
|
||||
if (regs.hang == HangType::Wait)
|
||||
goto SKIP;
|
||||
regs.wai = true;
|
||||
regs.hang = HangType::Wait;
|
||||
while(regs.wai) {
|
||||
L op_io();
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
SKIP: ;
|
||||
}
|
||||
regs.hang = HangType::None;
|
||||
}
|
||||
op_io();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
enum class HangType: unsigned { None, Wait, Stop };
|
||||
|
||||
struct flag_t {
|
||||
bool n, v, m, x, d, i, z, c;
|
||||
|
||||
|
@ -75,14 +73,11 @@ struct regs_t {
|
|||
|
||||
bool irq; //IRQ pin (0 = low, 1 = trigger)
|
||||
bool wai; //raised during wai, cleared after interrupt triggered
|
||||
|
||||
uint8 mdr; //memory data register
|
||||
uint16 vector; //interrupt vector address
|
||||
|
||||
HangType hang;
|
||||
|
||||
regs_t():
|
||||
a(r[0]), x(r[1]), y(r[2]), z(r[3]), s(r[4]), d(r[5]), db(0), e(false), irq(false), wai(false), mdr(0), vector(0), hang(HangType::None) {
|
||||
a(r[0]), x(r[1]), y(r[2]), z(r[3]), s(r[4]), d(r[5]), db(0), e(false), irq(false), wai(false), mdr(0), vector(0) {
|
||||
z = 0;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -26,10 +26,6 @@ void CPUcore::core_serialize(serializer &s) {
|
|||
s.integer(regs.mdr);
|
||||
s.integer(regs.vector);
|
||||
|
||||
unsigned junk = (unsigned)regs.hang;
|
||||
s.integer(junk);
|
||||
regs.hang = (HangType)junk;
|
||||
|
||||
s.integer(aa.d);
|
||||
s.integer(rd.d);
|
||||
s.integer(sp);
|
||||
|
|
|
@ -56,12 +56,8 @@ void CPU::Enter() { cpu.enter(); }
|
|||
void CPU::enter() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
|
||||
// we can only stop if there's enough time for at least one more event
|
||||
// on both the PPU and the SMP
|
||||
if (smp.clock < 0 && ppu.clock < 0) {
|
||||
scheduler.sync = Scheduler::SynchronizeMode::All;
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
scheduler.sync = Scheduler::SynchronizeMode::All;
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if(status.interrupt_pending) {
|
||||
|
|
|
@ -4,13 +4,10 @@
|
|||
namespace SNES {
|
||||
|
||||
#include "algorithms.cpp"
|
||||
//#include "opcodes.cpp"
|
||||
#include "opcodes.cpp"
|
||||
#include "disassembler.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
#include "uop.cpp"
|
||||
|
||||
/*
|
||||
void SMPcore::op_step() {
|
||||
switch(opcode = op_readpc()) {
|
||||
case 0x00: return op_nop();
|
||||
|
@ -271,5 +268,5 @@ void SMPcore::op_step() {
|
|||
case 0xff: return op_wait();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ struct SMPcore {
|
|||
word_t dp, sp, rd, wr, bit, ya;
|
||||
uint8 opcode;
|
||||
|
||||
int uindex;
|
||||
|
||||
void core_serialize(serializer&);
|
||||
string disassemble_opcode(uint16 addr);
|
||||
|
||||
|
|
|
@ -540,10 +540,6 @@ void SMPcore::op_stw_dp() {
|
|||
|
||||
void SMPcore::op_wait() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
regs.pc--; // repeat this opcode on next run
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
op_io();
|
||||
op_io();
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ void SMPcore::core_serialize(serializer &s) {
|
|||
s.integer(wr.w);
|
||||
s.integer(bit.w);
|
||||
s.integer(ya.w);
|
||||
|
||||
s.integer(uindex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -40,7 +40,7 @@ uint8 SMP::op_busread(uint16 addr) {
|
|||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
synchronize_cpu_force();
|
||||
synchronize_cpu();
|
||||
return cpu.port_read(addr);
|
||||
|
||||
case 0xf8: //RAM0
|
||||
|
@ -99,7 +99,7 @@ void SMP::op_buswrite(uint16 addr, uint8 data) {
|
|||
if(data & 0x30) {
|
||||
//one-time clearing of APU port read registers,
|
||||
//emulated by simulating CPU writes of 0x00
|
||||
synchronize_cpu_force();
|
||||
synchronize_cpu();
|
||||
if(data & 0x20) {
|
||||
cpu.port_write(2, 0x00);
|
||||
cpu.port_write(3, 0x00);
|
||||
|
@ -143,7 +143,7 @@ void SMP::op_buswrite(uint16 addr, uint8 data) {
|
|||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: //CPUIO3
|
||||
synchronize_cpu_force();
|
||||
synchronize_cpu();
|
||||
port_write(addr, data);
|
||||
break;
|
||||
|
||||
|
|
|
@ -23,17 +23,6 @@ void SMP::synchronize_cpu() {
|
|||
}
|
||||
}
|
||||
|
||||
void SMP::synchronize_cpu_force() {
|
||||
if(CPU::Threaded == true) {
|
||||
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All)
|
||||
co_switch(cpu.thread);
|
||||
else if(clock >= 0 && scheduler.sync == Scheduler::SynchronizeMode::All)
|
||||
interface()->message("SMP had to advance nondeterministically!");
|
||||
} else {
|
||||
while(clock >= 0) cpu.enter();
|
||||
}
|
||||
}
|
||||
|
||||
void SMP::synchronize_dsp() {
|
||||
if(DSP::Threaded == true) {
|
||||
if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread);
|
||||
|
@ -46,13 +35,6 @@ void SMP::Enter() { smp.enter(); }
|
|||
|
||||
void SMP::enter() {
|
||||
while(true) {
|
||||
// see comment in timing.cpp
|
||||
if(clock > +(768 * 24 * (int64)24000000))
|
||||
synchronize_cpu();
|
||||
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
|
||||
synchronize_cpu(); // when in CPU sync mode, always switch back to CPU as soon as possible
|
||||
}
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
@ -82,10 +64,6 @@ void SMP::reset() {
|
|||
create(Enter, system.apu_frequency());
|
||||
|
||||
regs.pc = 0xffc0;
|
||||
// exact value doesn't matter much, so long as "fetch" is next
|
||||
opcode = 0; // NOP
|
||||
uindex = 1; // fetch phase
|
||||
|
||||
regs.a = 0x00;
|
||||
regs.x = 0x00;
|
||||
regs.y = 0x00;
|
||||
|
|
|
@ -5,7 +5,6 @@ struct SMP : public Processor, public SMPcore {
|
|||
enum : bool { Threaded = true };
|
||||
alwaysinline void step(unsigned clocks);
|
||||
alwaysinline void synchronize_cpu();
|
||||
alwaysinline void synchronize_cpu_force();
|
||||
alwaysinline void synchronize_dsp();
|
||||
|
||||
uint8 port_read(uint2 port) const;
|
||||
|
|
|
@ -5,21 +5,11 @@ void SMP::add_clocks(unsigned clocks) {
|
|||
synchronize_dsp();
|
||||
|
||||
#if defined(DEBUGGER)
|
||||
#error -DDEBUGGER SMP runtosave() correctness not checked
|
||||
synchronize_cpu();
|
||||
#else
|
||||
//forcefully sync S-SMP to S-CPU in case chips are not communicating
|
||||
//sync if S-SMP is more than 24 samples ahead of S-CPU
|
||||
/*
|
||||
our new smp design guarantees that there is at most one required synchronize_cpu() per uop,
|
||||
inside an op_busread() or op_buswrite(). this extra synchronize can cause problems if we
|
||||
swap out of the SMP at the beginning of a uop with an add_clocks() call when there is an
|
||||
important op_busread() / op_buswrite() later on. the SMP will need to finish that uop in
|
||||
order to reach a savable state, but it might never get to do so until it's too late (ie,
|
||||
scheduler.sync == Scheduler.SynchronizeMode::All). so we remove this call and instead
|
||||
do catchup sync in the main Enter() loop.
|
||||
*/
|
||||
//if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu();
|
||||
if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue