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:
nattthebear 2017-06-10 07:21:29 -04:00
parent 767ae4d8b9
commit 9ecf86a80a
20 changed files with 1100 additions and 4368 deletions

View File

@ -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();
}
}

View File

@ -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));

View File

@ -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();

View File

@ -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

View File

@ -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();
}
}

View File

@ -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()])();
}
}

View File

@ -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();
}

View File

@ -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;
}
};

View File

@ -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);

View File

@ -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) {

View File

@ -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();
}
}
*/
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
}