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();
}
@ -28,33 +25,15 @@ void PPU::synchronize_cpu() {
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
}
while(true) {
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) {
@ -372,8 +349,6 @@ void PPU::reset() {
create(Enter, system.cpu_frequency());
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));

View File

@ -1,84 +1,78 @@
class PPU : public Processor, public PPUcounter {
public:
uint8* vram; //[128 * 1024]
uint8* oam; //[544]
uint8* cgram; //[512]
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
#include "render/render.hpp"
class PPU : public Processor, public PPUcounter {
public:
uint8* vram; //[128 * 1024]
uint8* oam; //[544]
uint8* cgram; //[512]
int uindex;
uint32 *surface;
uint32 *output;
uint8 ppu1_version;
uint8 ppu2_version;
static void Enter();
void add_clocks(unsigned clocks);
uint8 region;
unsigned line;
enum { NTSC = 0, PAL = 1 };
enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 };
enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 };
struct {
bool interlace;
bool overscan;
} display;
struct {
//$2101
uint8 oam_basesize;
uint8 oam_nameselect;
uint16 oam_tdaddr;
//$210d-$210e
uint16 m7_hofs, m7_vofs;
//$211b-$2120
uint16 m7a, m7b, m7c, m7d, m7x, m7y;
} cache;
alwaysinline bool interlace() const { return display.interlace; }
alwaysinline bool overscan() const { return display.overscan; }
alwaysinline bool hires() const { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); }
uint16 mosaic_table[16][4096];
void render_line();
void update_oam_status();
//required functions
void scanline();
void render_scanline();
void frame();
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
#include "render/render.hpp"
uint32 *surface;
uint32 *output;
uint8 ppu1_version;
uint8 ppu2_version;
static void Enter();
void add_clocks(unsigned clocks);
uint8 region;
unsigned line;
enum { NTSC = 0, PAL = 1 };
enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 };
enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 };
struct {
bool interlace;
bool overscan;
} display;
struct {
//$2101
uint8 oam_basesize;
uint8 oam_nameselect;
uint16 oam_tdaddr;
//$210d-$210e
uint16 m7_hofs, m7_vofs;
//$211b-$2120
uint16 m7a, m7b, m7c, m7d, m7x, m7y;
} cache;
alwaysinline bool interlace() const { return display.interlace; }
alwaysinline bool overscan() const { return display.overscan; }
alwaysinline bool hires() const { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); }
uint16 mosaic_table[16][4096];
void render_line();
void update_oam_status();
//required functions
void scanline();
void render_scanline();
void frame();
void enter();
void enter1();
void enter2();
void enter3();
void enter4();
void enable();
void power();
void reset();
bool layer_enabled[5][4];
void layer_enable(unsigned layer, unsigned priority, bool enable);
unsigned frameskip;
unsigned framecounter;
void set_frameskip(unsigned frameskip);
void serialize(serializer&);
void initialize();
PPU();
~PPU();
};
extern PPU ppu;
void enable();
void power();
void reset();
bool layer_enabled[5][4];
void layer_enable(unsigned layer, unsigned priority, bool enable);
unsigned frameskip;
unsigned framecounter;
void set_frameskip(unsigned frameskip);
void serialize(serializer&);
void initialize();
PPU();
~PPU();
};
extern PPU ppu;

View File

@ -1,210 +1,208 @@
#ifdef PPU_CPP
void PPUcounter::serialize(serializer &s) {
s.integer(status.interlace);
s.integer(status.field);
s.integer(status.vcounter);
s.integer(status.hcounter);
s.array(history.field);
s.array(history.vcounter);
s.array(history.hcounter);
s.integer(history.index);
}
void PPU::serialize(serializer &s) {
Processor::serialize(s);
PPUcounter::serialize(s);
s.array(vram,128 * 1024);
s.array(oam,544);
s.array(cgram,512);
s.integer(ppu1_version);
s.integer(ppu2_version);
s.integer(region);
s.integer(line);
s.integer(display.interlace);
s.integer(display.overscan);
s.integer(cache.oam_basesize);
s.integer(cache.oam_nameselect);
s.integer(cache.oam_tdaddr);
s.integer(regs.ppu1_mdr);
s.integer(regs.ppu2_mdr);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_y[n]);
s.integer(regs.ioamaddr);
s.integer(regs.icgramaddr);
s.integer(regs.display_disabled);
s.integer(regs.display_brightness);
s.integer(regs.oam_basesize);
s.integer(regs.oam_nameselect);
s.integer(regs.oam_tdaddr);
s.integer(regs.oam_baseaddr);
s.integer(regs.oam_addr);
s.integer(regs.oam_priority);
s.integer(regs.oam_firstsprite);
s.integer(regs.oam_latchdata);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_tilesize[n]);
s.integer(regs.bg3_priority);
s.integer(regs.bg_mode);
s.integer(regs.mosaic_size);
for(unsigned n = 0; n < 4; n++) s.integer(regs.mosaic_enabled[n]);
s.integer(regs.mosaic_countdown);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_scaddr[n]);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_scsize[n]);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_tdaddr[n]);
s.integer(regs.bg_ofslatch);
s.integer(regs.m7_hofs);
s.integer(regs.m7_vofs);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_hofs[n]);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_vofs[n]);
s.integer(regs.vram_incmode);
s.integer(regs.vram_mapping);
s.integer(regs.vram_incsize);
s.integer(regs.vram_addr);
s.integer(regs.mode7_repeat);
s.integer(regs.mode7_vflip);
s.integer(regs.mode7_hflip);
s.integer(regs.m7_latch);
s.integer(regs.m7a);
s.integer(regs.m7b);
s.integer(regs.m7c);
s.integer(regs.m7d);
s.integer(regs.m7x);
s.integer(regs.m7y);
s.integer(regs.cgram_addr);
s.integer(regs.cgram_latchdata);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window1_enabled[n]);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window1_invert [n]);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window2_enabled[n]);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window2_invert [n]);
s.integer(regs.window1_left);
s.integer(regs.window1_right);
s.integer(regs.window2_left);
s.integer(regs.window2_right);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window_mask[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.bg_enabled[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.bgsub_enabled[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.window_enabled[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.sub_window_enabled[n]);
s.integer(regs.color_mask);
s.integer(regs.colorsub_mask);
s.integer(regs.addsub_mode);
s.integer(regs.direct_color);
s.integer(regs.color_mode);
s.integer(regs.color_halve);
for(unsigned n = 0; n < 6; n++) s.integer(regs.color_enabled[n]);
s.integer(regs.color_r);
s.integer(regs.color_g);
s.integer(regs.color_b);
s.integer(regs.color_rgb);
s.integer(regs.mode7_extbg);
s.integer(regs.pseudo_hires);
s.integer(regs.overscan);
s.integer(regs.scanlines);
s.integer(regs.oam_interlace);
s.integer(regs.interlace);
s.integer(regs.hcounter);
s.integer(regs.vcounter);
s.integer(regs.latch_hcounter);
s.integer(regs.latch_vcounter);
s.integer(regs.counters_latched);
s.integer(regs.vram_readbuffer);
s.integer(regs.time_over);
s.integer(regs.range_over);
s.integer(regs.oam_itemcount);
s.integer(regs.oam_tilecount);
for(unsigned n = 0; n < 256; n++) {
s.integer(pixel_cache[n].src_main);
s.integer(pixel_cache[n].src_sub);
s.integer(pixel_cache[n].bg_main);
s.integer(pixel_cache[n].bg_sub);
s.integer(pixel_cache[n].ce_main);
s.integer(pixel_cache[n].ce_sub);
s.integer(pixel_cache[n].pri_main);
s.integer(pixel_cache[n].pri_sub);
}
//zero TODO - only on load
//better to just take a small speed hit than store all of bg_tiledata[3][] ...
flush_tiledata_cache();
for(unsigned n = 0; n < 6; n++) {
s.array(window[n].main, 256);
s.array(window[n].sub, 256);
}
for(unsigned n = 0; n < 4; n++) {
s.integer(bg_info[n].tw);
s.integer(bg_info[n].th);
s.integer(bg_info[n].mx);
s.integer(bg_info[n].my);
s.integer(bg_info[n].scx);
s.integer(bg_info[n].scy);
}
for(unsigned n = 0; n < 128; n++) {
s.integer(sprite_list[n].width);
s.integer(sprite_list[n].height);
s.integer(sprite_list[n].x);
s.integer(sprite_list[n].y);
s.integer(sprite_list[n].character);
s.integer(sprite_list[n].use_nameselect);
s.integer(sprite_list[n].vflip);
s.integer(sprite_list[n].hflip);
s.integer(sprite_list[n].palette);
s.integer(sprite_list[n].priority);
s.integer(sprite_list[n].size);
}
s.integer(sprite_list_valid);
s.integer(active_sprite);
s.array(oam_itemlist, 32);
for(unsigned n = 0; n < 34; n++) {
s.integer(oam_tilelist[n].x);
s.integer(oam_tilelist[n].y);
s.integer(oam_tilelist[n].pri);
s.integer(oam_tilelist[n].pal);
s.integer(oam_tilelist[n].tile);
s.integer(oam_tilelist[n].hflip);
}
s.array(oam_line_pal, 256);
s.array(oam_line_pri, 256);
#ifdef PPU_CPP
s.integer(uindex);
}
#endif
void PPUcounter::serialize(serializer &s) {
s.integer(status.interlace);
s.integer(status.field);
s.integer(status.vcounter);
s.integer(status.hcounter);
s.array(history.field);
s.array(history.vcounter);
s.array(history.hcounter);
s.integer(history.index);
}
void PPU::serialize(serializer &s) {
Processor::serialize(s);
PPUcounter::serialize(s);
s.array(vram,128 * 1024);
s.array(oam,544);
s.array(cgram,512);
s.integer(ppu1_version);
s.integer(ppu2_version);
s.integer(region);
s.integer(line);
s.integer(display.interlace);
s.integer(display.overscan);
s.integer(cache.oam_basesize);
s.integer(cache.oam_nameselect);
s.integer(cache.oam_tdaddr);
s.integer(regs.ppu1_mdr);
s.integer(regs.ppu2_mdr);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_y[n]);
s.integer(regs.ioamaddr);
s.integer(regs.icgramaddr);
s.integer(regs.display_disabled);
s.integer(regs.display_brightness);
s.integer(regs.oam_basesize);
s.integer(regs.oam_nameselect);
s.integer(regs.oam_tdaddr);
s.integer(regs.oam_baseaddr);
s.integer(regs.oam_addr);
s.integer(regs.oam_priority);
s.integer(regs.oam_firstsprite);
s.integer(regs.oam_latchdata);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_tilesize[n]);
s.integer(regs.bg3_priority);
s.integer(regs.bg_mode);
s.integer(regs.mosaic_size);
for(unsigned n = 0; n < 4; n++) s.integer(regs.mosaic_enabled[n]);
s.integer(regs.mosaic_countdown);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_scaddr[n]);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_scsize[n]);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_tdaddr[n]);
s.integer(regs.bg_ofslatch);
s.integer(regs.m7_hofs);
s.integer(regs.m7_vofs);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_hofs[n]);
for(unsigned n = 0; n < 4; n++) s.integer(regs.bg_vofs[n]);
s.integer(regs.vram_incmode);
s.integer(regs.vram_mapping);
s.integer(regs.vram_incsize);
s.integer(regs.vram_addr);
s.integer(regs.mode7_repeat);
s.integer(regs.mode7_vflip);
s.integer(regs.mode7_hflip);
s.integer(regs.m7_latch);
s.integer(regs.m7a);
s.integer(regs.m7b);
s.integer(regs.m7c);
s.integer(regs.m7d);
s.integer(regs.m7x);
s.integer(regs.m7y);
s.integer(regs.cgram_addr);
s.integer(regs.cgram_latchdata);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window1_enabled[n]);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window1_invert [n]);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window2_enabled[n]);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window2_invert [n]);
s.integer(regs.window1_left);
s.integer(regs.window1_right);
s.integer(regs.window2_left);
s.integer(regs.window2_right);
for(unsigned n = 0; n < 6; n++) s.integer(regs.window_mask[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.bg_enabled[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.bgsub_enabled[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.window_enabled[n]);
for(unsigned n = 0; n < 5; n++) s.integer(regs.sub_window_enabled[n]);
s.integer(regs.color_mask);
s.integer(regs.colorsub_mask);
s.integer(regs.addsub_mode);
s.integer(regs.direct_color);
s.integer(regs.color_mode);
s.integer(regs.color_halve);
for(unsigned n = 0; n < 6; n++) s.integer(regs.color_enabled[n]);
s.integer(regs.color_r);
s.integer(regs.color_g);
s.integer(regs.color_b);
s.integer(regs.color_rgb);
s.integer(regs.mode7_extbg);
s.integer(regs.pseudo_hires);
s.integer(regs.overscan);
s.integer(regs.scanlines);
s.integer(regs.oam_interlace);
s.integer(regs.interlace);
s.integer(regs.hcounter);
s.integer(regs.vcounter);
s.integer(regs.latch_hcounter);
s.integer(regs.latch_vcounter);
s.integer(regs.counters_latched);
s.integer(regs.vram_readbuffer);
s.integer(regs.time_over);
s.integer(regs.range_over);
s.integer(regs.oam_itemcount);
s.integer(regs.oam_tilecount);
for(unsigned n = 0; n < 256; n++) {
s.integer(pixel_cache[n].src_main);
s.integer(pixel_cache[n].src_sub);
s.integer(pixel_cache[n].bg_main);
s.integer(pixel_cache[n].bg_sub);
s.integer(pixel_cache[n].ce_main);
s.integer(pixel_cache[n].ce_sub);
s.integer(pixel_cache[n].pri_main);
s.integer(pixel_cache[n].pri_sub);
}
//zero TODO - only on load
//better to just take a small speed hit than store all of bg_tiledata[3][] ...
flush_tiledata_cache();
for(unsigned n = 0; n < 6; n++) {
s.array(window[n].main, 256);
s.array(window[n].sub, 256);
}
for(unsigned n = 0; n < 4; n++) {
s.integer(bg_info[n].tw);
s.integer(bg_info[n].th);
s.integer(bg_info[n].mx);
s.integer(bg_info[n].my);
s.integer(bg_info[n].scx);
s.integer(bg_info[n].scy);
}
for(unsigned n = 0; n < 128; n++) {
s.integer(sprite_list[n].width);
s.integer(sprite_list[n].height);
s.integer(sprite_list[n].x);
s.integer(sprite_list[n].y);
s.integer(sprite_list[n].character);
s.integer(sprite_list[n].use_nameselect);
s.integer(sprite_list[n].vflip);
s.integer(sprite_list[n].hflip);
s.integer(sprite_list[n].palette);
s.integer(sprite_list[n].priority);
s.integer(sprite_list[n].size);
}
s.integer(sprite_list_valid);
s.integer(active_sprite);
s.array(oam_itemlist, 32);
for(unsigned n = 0; n < 34; n++) {
s.integer(oam_tilelist[n].x);
s.integer(oam_tilelist[n].y);
s.integer(oam_tilelist[n].pri);
s.integer(oam_tilelist[n].pal);
s.integer(oam_tilelist[n].tile);
s.integer(oam_tilelist[n].hflip);
}
s.array(oam_line_pal, 256);
s.array(oam_line_pri, 256);
}
#endif

View File

@ -1,87 +1,82 @@
#include <snes/snes.hpp>
#define HITACHIDSP_CPP
namespace SNES {
#include "memory.cpp"
#include "opcodes.cpp"
#include "registers.cpp"
#include "serialization.cpp"
HitachiDSP hitachidsp;
//zero 01-sep-2014 - dont clobber these when reconstructing!
unsigned HitachiDSP::frequency;
uint24 HitachiDSP::dataROM[1024];
void HitachiDSP::Enter() { hitachidsp.enter(); }
void HitachiDSP::enter() {
#include <snes/snes.hpp>
#define HITACHIDSP_CPP
namespace SNES {
#include "memory.cpp"
#include "opcodes.cpp"
#include "registers.cpp"
#include "serialization.cpp"
HitachiDSP hitachidsp;
//zero 01-sep-2014 - dont clobber these when reconstructing!
unsigned HitachiDSP::frequency;
uint24 HitachiDSP::dataROM[1024];
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(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);
break;
case State::DMA:
for(unsigned n = 0; n < regs.dma_length; n++) {
bus.write(regs.dma_target + n, bus.read(regs.dma_source + n));
step(2);
}
state = State::Idle;
break;
case State::Execute:
unsigned offset = regs.program_offset + regs.pc * 2;
opcode = bus_read(offset + 0) << 0;
opcode |= bus_read(offset + 1) << 8;
regs.pc = (regs.pc & 0xffff00) | ((regs.pc + 1) & 0x0000ff);
exec();
step(1);
break;
}
switch(state) {
case State::Idle:
step(1);
break;
case State::DMA:
for(unsigned n = 0; n < regs.dma_length; n++) {
bus.write(regs.dma_target + n, bus.read(regs.dma_source + n));
step(2);
}
state = State::Idle;
break;
case State::Execute:
unsigned offset = regs.program_offset + regs.pc * 2;
opcode = bus_read(offset + 0) << 0;
opcode |= bus_read(offset + 1) << 8;
regs.pc = (regs.pc & 0xffff00) | ((regs.pc + 1) & 0x0000ff);
exec();
step(1);
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();
}
}
void HitachiDSP::init() {
}
void HitachiDSP::load() {
}
void HitachiDSP::unload() {
}
void HitachiDSP::power() {
}
void HitachiDSP::reset() {
create(HitachiDSP::Enter, frequency);
state = State::Idle;
regs.n = 0;
regs.z = 0;
regs.c = 0;
regs.dma_source = 0x000000;
regs.dma_length = 0x0000;
regs.dma_target = 0x000000;
regs.r1f48 = 0x00;
regs.program_offset = 0x000000;
regs.r1f4c = 0x00;
regs.page_number = 0x0000;
regs.program_counter = 0x00;
regs.r1f50 = 0x33;
regs.r1f51 = 0x00;
regs.r1f52 = 0x01;
}
}
synchronize_cpu();
}
}
void HitachiDSP::init() {
}
void HitachiDSP::load() {
}
void HitachiDSP::unload() {
}
void HitachiDSP::power() {
}
void HitachiDSP::reset() {
create(HitachiDSP::Enter, frequency);
state = State::Idle;
regs.n = 0;
regs.z = 0;
regs.c = 0;
regs.dma_source = 0x000000;
regs.dma_length = 0x0000;
regs.dma_target = 0x000000;
regs.r1f48 = 0x00;
regs.program_offset = 0x000000;
regs.r1f4c = 0x00;
regs.page_number = 0x0000;
regs.program_counter = 0x00;
regs.r1f50 = 0x33;
regs.r1f51 = 0x00;
regs.r1f52 = 0x01;
}
}

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

@ -1,184 +1,180 @@
#include <snes/snes.hpp>
#define CPU_CPP
namespace SNES {
CPU cpu;
#include "serialization.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
#include "timing/timing.cpp"
void CPU::step(unsigned clocks) {
smp.clock -= clocks * (uint64)smp.frequency;
ppu.clock -= clocks;
for(unsigned i = 0; i < coprocessors.size(); i++) {
Processor &chip = *coprocessors[i];
chip.clock -= clocks * (uint64)chip.frequency;
}
input.port1->clock -= clocks * (uint64)input.port1->frequency;
input.port2->clock -= clocks * (uint64)input.port2->frequency;
synchronize_controllers();
}
void CPU::synchronize_smp() {
if(SMP::Threaded == true) {
if(smp.clock < 0) co_switch(smp.thread);
} else {
while(smp.clock < 0) smp.enter();
}
}
void CPU::synchronize_ppu() {
if(PPU::Threaded == true) {
if(ppu.clock < 0) co_switch(ppu.thread);
} else {
while(ppu.clock < 0) ppu.enter();
}
}
void CPU::synchronize_coprocessors() {
for(unsigned i = 0; i < coprocessors.size(); i++) {
Processor &chip = *coprocessors[i];
if(chip.clock < 0) co_switch(chip.thread);
}
}
void CPU::synchronize_controllers() {
if(input.port1->clock < 0) co_switch(input.port1->thread);
if(input.port2->clock < 0) co_switch(input.port2->thread);
}
void CPU::Enter() { cpu.enter(); }
void CPU::enter() {
while(true) {
#include <snes/snes.hpp>
#define CPU_CPP
namespace SNES {
CPU cpu;
#include "serialization.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
#include "timing/timing.cpp"
void CPU::step(unsigned clocks) {
smp.clock -= clocks * (uint64)smp.frequency;
ppu.clock -= clocks;
for(unsigned i = 0; i < coprocessors.size(); i++) {
Processor &chip = *coprocessors[i];
chip.clock -= clocks * (uint64)chip.frequency;
}
input.port1->clock -= clocks * (uint64)input.port1->frequency;
input.port2->clock -= clocks * (uint64)input.port2->frequency;
synchronize_controllers();
}
void CPU::synchronize_smp() {
if(SMP::Threaded == true) {
if(smp.clock < 0) co_switch(smp.thread);
} else {
while(smp.clock < 0) smp.enter();
}
}
void CPU::synchronize_ppu() {
if(PPU::Threaded == true) {
if(ppu.clock < 0) co_switch(ppu.thread);
} else {
while(ppu.clock < 0) ppu.enter();
}
}
void CPU::synchronize_coprocessors() {
for(unsigned i = 0; i < coprocessors.size(); i++) {
Processor &chip = *coprocessors[i];
if(chip.clock < 0) co_switch(chip.thread);
}
}
void CPU::synchronize_controllers() {
if(input.port1->clock < 0) co_switch(input.port1->thread);
if(input.port2->clock < 0) co_switch(input.port2->thread);
}
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);
}
}
if(status.interrupt_pending) {
status.interrupt_pending = false;
if(status.nmi_pending) {
status.nmi_pending = false;
regs.vector = (regs.e == false ? 0xffea : 0xfffa);
op_irq();
debugger.op_nmi();
} else if(status.irq_pending) {
status.irq_pending = false;
regs.vector = (regs.e == false ? 0xffee : 0xfffe);
op_irq();
debugger.op_irq();
} else if(status.reset_pending) {
status.reset_pending = false;
add_clocks(186);
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
}
}
op_step();
}
}
void CPU::op_step() {
debugger.op_exec(regs.pc.d);
if (interface()->wanttrace & TRACE_CPU_MASK)
{
char tmp[512];
disassemble_opcode(tmp, regs.pc.d);
tmp[511] = 0;
interface()->cpuTrace(TRACE_CPU, tmp);
}
(this->*opcode_table[op_readpcfirst()])();
}
void CPU::enable() {
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; };
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
}
void CPU::power() {
cpu_version = config.cpu.version;
for(int i=0;i<128*1024;i++) wram[i] = random(config.cpu.wram_init_value);
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
mmio_power();
dma_power();
timing_power();
//zero 01-dec-2012
//gotta clear these to something, sometime
aa.d = rd.d = sp = dp = 0;
}
void CPU::reset() {
create(Enter, system.cpu_frequency());
coprocessors.reset();
PPUcounter::reset();
//note: some registers are not fully reset by SNES
regs.pc = 0x000000;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
regs.wai = false;
regs.vector = 0xfffc; //reset vector address
update_table();
mmio_reset();
dma_reset();
timing_reset();
}
CPU::CPU()
: wram(nullptr)
{
PPUcounter::scanline = { &CPU::scanline, this };
}
CPU::~CPU() {
interface()->freeSharedMemory(wram);
}
void CPU::initialize()
{
wram = (uint8*)interface()->allocSharedMemory("WRAM",128 * 1024);
}
}
scheduler.sync = Scheduler::SynchronizeMode::All;
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
if(status.interrupt_pending) {
status.interrupt_pending = false;
if(status.nmi_pending) {
status.nmi_pending = false;
regs.vector = (regs.e == false ? 0xffea : 0xfffa);
op_irq();
debugger.op_nmi();
} else if(status.irq_pending) {
status.irq_pending = false;
regs.vector = (regs.e == false ? 0xffee : 0xfffe);
op_irq();
debugger.op_irq();
} else if(status.reset_pending) {
status.reset_pending = false;
add_clocks(186);
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
}
}
op_step();
}
}
void CPU::op_step() {
debugger.op_exec(regs.pc.d);
if (interface()->wanttrace & TRACE_CPU_MASK)
{
char tmp[512];
disassemble_opcode(tmp, regs.pc.d);
tmp[511] = 0;
interface()->cpuTrace(TRACE_CPU, tmp);
}
(this->*opcode_table[op_readpcfirst()])();
}
void CPU::enable() {
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; };
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
}
void CPU::power() {
cpu_version = config.cpu.version;
for(int i=0;i<128*1024;i++) wram[i] = random(config.cpu.wram_init_value);
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
mmio_power();
dma_power();
timing_power();
//zero 01-dec-2012
//gotta clear these to something, sometime
aa.d = rd.d = sp = dp = 0;
}
void CPU::reset() {
create(Enter, system.cpu_frequency());
coprocessors.reset();
PPUcounter::reset();
//note: some registers are not fully reset by SNES
regs.pc = 0x000000;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
regs.wai = false;
regs.vector = 0xfffc; //reset vector address
update_table();
mmio_reset();
dma_reset();
timing_reset();
}
CPU::CPU()
: wram(nullptr)
{
PPUcounter::scanline = { &CPU::scanline, this };
}
CPU::~CPU() {
interface()->freeSharedMemory(wram);
}
void CPU::initialize()
{
wram = (uint8*)interface()->allocSharedMemory("WRAM",128 * 1024);
}
}

View File

@ -1,275 +1,272 @@
#include <snes/snes.hpp>
#define SMPCORE_CPP
namespace SNES {
#include "algorithms.cpp"
//#include "opcodes.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"
#include <snes/snes.hpp>
#include "uop.cpp"
#define SMPCORE_CPP
namespace SNES {
/*
void SMPcore::op_step() {
switch(opcode = op_readpc()) {
case 0x00: return op_nop();
case 0x01: return op_jst();
case 0x02: return op_set_bit();
case 0x03: return op_branch_bit();
case 0x04: return op_read_dp<&SMPcore::op_or>(regs.a);
case 0x05: return op_read_addr<&SMPcore::op_or>(regs.a);
case 0x06: return op_read_ix<&SMPcore::op_or>();
case 0x07: return op_read_idpx<&SMPcore::op_or>();
case 0x08: return op_read_const<&SMPcore::op_or>(regs.a);
case 0x09: return op_write_dp_dp<&SMPcore::op_or>();
case 0x0a: return op_set_addr_bit();
case 0x0b: return op_adjust_dp<&SMPcore::op_asl>();
case 0x0c: return op_adjust_addr<&SMPcore::op_asl>();
case 0x0d: return op_push(regs.p);
case 0x0e: return op_test_addr(1);
case 0x0f: return op_brk();
case 0x10: return op_branch(regs.p.n == 0);
case 0x11: return op_jst();
case 0x12: return op_set_bit();
case 0x13: return op_branch_bit();
case 0x14: return op_read_dpi<&SMPcore::op_or>(regs.a, regs.x);
case 0x15: return op_read_addri<&SMPcore::op_or>(regs.x);
case 0x16: return op_read_addri<&SMPcore::op_or>(regs.y);
case 0x17: return op_read_idpy<&SMPcore::op_or>();
case 0x18: return op_write_dp_const<&SMPcore::op_or>();
case 0x19: return op_write_ix_iy<&SMPcore::op_or>();
case 0x1a: return op_adjust_dpw(-1);
case 0x1b: return op_adjust_dpx<&SMPcore::op_asl>();
case 0x1c: return op_adjust<&SMPcore::op_asl>(regs.a);
case 0x1d: return op_adjust<&SMPcore::op_dec>(regs.x);
case 0x1e: return op_read_addr<&SMPcore::op_cmp>(regs.x);
case 0x1f: return op_jmp_iaddrx();
case 0x20: return op_set_flag(regs.p.p, 0);
case 0x21: return op_jst();
case 0x22: return op_set_bit();
case 0x23: return op_branch_bit();
case 0x24: return op_read_dp<&SMPcore::op_and>(regs.a);
case 0x25: return op_read_addr<&SMPcore::op_and>(regs.a);
case 0x26: return op_read_ix<&SMPcore::op_and>();
case 0x27: return op_read_idpx<&SMPcore::op_and>();
case 0x28: return op_read_const<&SMPcore::op_and>(regs.a);
case 0x29: return op_write_dp_dp<&SMPcore::op_and>();
case 0x2a: return op_set_addr_bit();
case 0x2b: return op_adjust_dp<&SMPcore::op_rol>();
case 0x2c: return op_adjust_addr<&SMPcore::op_rol>();
case 0x2d: return op_push(regs.a);
case 0x2e: return op_bne_dp();
case 0x2f: return op_branch(true);
case 0x30: return op_branch(regs.p.n == 1);
case 0x31: return op_jst();
case 0x32: return op_set_bit();
case 0x33: return op_branch_bit();
case 0x34: return op_read_dpi<&SMPcore::op_and>(regs.a, regs.x);
case 0x35: return op_read_addri<&SMPcore::op_and>(regs.x);
case 0x36: return op_read_addri<&SMPcore::op_and>(regs.y);
case 0x37: return op_read_idpy<&SMPcore::op_and>();
case 0x38: return op_write_dp_const<&SMPcore::op_and>();
case 0x39: return op_write_ix_iy<&SMPcore::op_and>();
case 0x3a: return op_adjust_dpw(+1);
case 0x3b: return op_adjust_dpx<&SMPcore::op_rol>();
case 0x3c: return op_adjust<&SMPcore::op_rol>(regs.a);
case 0x3d: return op_adjust<&SMPcore::op_inc>(regs.x);
case 0x3e: return op_read_dp<&SMPcore::op_cmp>(regs.x);
case 0x3f: return op_jsr_addr();
case 0x40: return op_set_flag(regs.p.p, 1);
case 0x41: return op_jst();
case 0x42: return op_set_bit();
case 0x43: return op_branch_bit();
case 0x44: return op_read_dp<&SMPcore::op_eor>(regs.a);
case 0x45: return op_read_addr<&SMPcore::op_eor>(regs.a);
case 0x46: return op_read_ix<&SMPcore::op_eor>();
case 0x47: return op_read_idpx<&SMPcore::op_eor>();
case 0x48: return op_read_const<&SMPcore::op_eor>(regs.a);
case 0x49: return op_write_dp_dp<&SMPcore::op_eor>();
case 0x4a: return op_set_addr_bit();
case 0x4b: return op_adjust_dp<&SMPcore::op_lsr>();
case 0x4c: return op_adjust_addr<&SMPcore::op_lsr>();
case 0x4d: return op_push(regs.x);
case 0x4e: return op_test_addr(0);
case 0x4f: return op_jsp_dp();
case 0x50: return op_branch(regs.p.v == 0);
case 0x51: return op_jst();
case 0x52: return op_set_bit();
case 0x53: return op_branch_bit();
case 0x54: return op_read_dpi<&SMPcore::op_eor>(regs.a, regs.x);
case 0x55: return op_read_addri<&SMPcore::op_eor>(regs.x);
case 0x56: return op_read_addri<&SMPcore::op_eor>(regs.y);
case 0x57: return op_read_idpy<&SMPcore::op_eor>();
case 0x58: return op_write_dp_const<&SMPcore::op_eor>();
case 0x59: return op_write_ix_iy<&SMPcore::op_eor>();
case 0x5a: return op_read_dpw<&SMPcore::op_cpw>();
case 0x5b: return op_adjust_dpx<&SMPcore::op_lsr>();
case 0x5c: return op_adjust<&SMPcore::op_lsr>(regs.a);
case 0x5d: return op_transfer(regs.a, regs.x);
case 0x5e: return op_read_addr<&SMPcore::op_cmp>(regs.y);
case 0x5f: return op_jmp_addr();
case 0x60: return op_set_flag(regs.p.c, 0);
case 0x61: return op_jst();
case 0x62: return op_set_bit();
case 0x63: return op_branch_bit();
case 0x64: return op_read_dp<&SMPcore::op_cmp>(regs.a);
case 0x65: return op_read_addr<&SMPcore::op_cmp>(regs.a);
case 0x66: return op_read_ix<&SMPcore::op_cmp>();
case 0x67: return op_read_idpx<&SMPcore::op_cmp>();
case 0x68: return op_read_const<&SMPcore::op_cmp>(regs.a);
case 0x69: return op_write_dp_dp<&SMPcore::op_cmp>();
case 0x6a: return op_set_addr_bit();
case 0x6b: return op_adjust_dp<&SMPcore::op_ror>();
case 0x6c: return op_adjust_addr<&SMPcore::op_ror>();
case 0x6d: return op_push(regs.y);
case 0x6e: return op_bne_dpdec();
case 0x6f: return op_rts();
case 0x70: return op_branch(regs.p.v == 1);
case 0x71: return op_jst();
case 0x72: return op_set_bit();
case 0x73: return op_branch_bit();
case 0x74: return op_read_dpi<&SMPcore::op_cmp>(regs.a, regs.x);
case 0x75: return op_read_addri<&SMPcore::op_cmp>(regs.x);
case 0x76: return op_read_addri<&SMPcore::op_cmp>(regs.y);
case 0x77: return op_read_idpy<&SMPcore::op_cmp>();
case 0x78: return op_write_dp_const<&SMPcore::op_cmp>();
case 0x79: return op_write_ix_iy<&SMPcore::op_cmp>();
case 0x7a: return op_read_dpw<&SMPcore::op_adw>();
case 0x7b: return op_adjust_dpx<&SMPcore::op_ror>();
case 0x7c: return op_adjust<&SMPcore::op_ror>(regs.a);
case 0x7d: return op_transfer(regs.x, regs.a);
case 0x7e: return op_read_dp<&SMPcore::op_cmp>(regs.y);
case 0x7f: return op_rti();
case 0x80: return op_set_flag(regs.p.c, 1);
case 0x81: return op_jst();
case 0x82: return op_set_bit();
case 0x83: return op_branch_bit();
case 0x84: return op_read_dp<&SMPcore::op_adc>(regs.a);
case 0x85: return op_read_addr<&SMPcore::op_adc>(regs.a);
case 0x86: return op_read_ix<&SMPcore::op_adc>();
case 0x87: return op_read_idpx<&SMPcore::op_adc>();
case 0x88: return op_read_const<&SMPcore::op_adc>(regs.a);
case 0x89: return op_write_dp_dp<&SMPcore::op_adc>();
case 0x8a: return op_set_addr_bit();
case 0x8b: return op_adjust_dp<&SMPcore::op_dec>();
case 0x8c: return op_adjust_addr<&SMPcore::op_dec>();
case 0x8d: return op_read_const<&SMPcore::op_ld>(regs.y);
case 0x8e: return op_plp();
case 0x8f: return op_write_dp_const<&SMPcore::op_st>();
case 0x90: return op_branch(regs.p.c == 0);
case 0x91: return op_jst();
case 0x92: return op_set_bit();
case 0x93: return op_branch_bit();
case 0x94: return op_read_dpi<&SMPcore::op_adc>(regs.a, regs.x);
case 0x95: return op_read_addri<&SMPcore::op_adc>(regs.x);
case 0x96: return op_read_addri<&SMPcore::op_adc>(regs.y);
case 0x97: return op_read_idpy<&SMPcore::op_adc>();
case 0x98: return op_write_dp_const<&SMPcore::op_adc>();
case 0x99: return op_write_ix_iy<&SMPcore::op_adc>();
case 0x9a: return op_read_dpw<&SMPcore::op_sbw>();
case 0x9b: return op_adjust_dpx<&SMPcore::op_dec>();
case 0x9c: return op_adjust<&SMPcore::op_dec>(regs.a);
case 0x9d: return op_transfer(regs.s, regs.x);
case 0x9e: return op_div_ya_x();
case 0x9f: return op_xcn();
case 0xa0: return op_set_flag(regs.p.i, 1);
case 0xa1: return op_jst();
case 0xa2: return op_set_bit();
case 0xa3: return op_branch_bit();
case 0xa4: return op_read_dp<&SMPcore::op_sbc>(regs.a);
case 0xa5: return op_read_addr<&SMPcore::op_sbc>(regs.a);
case 0xa6: return op_read_ix<&SMPcore::op_sbc>();
case 0xa7: return op_read_idpx<&SMPcore::op_sbc>();
case 0xa8: return op_read_const<&SMPcore::op_sbc>(regs.a);
case 0xa9: return op_write_dp_dp<&SMPcore::op_sbc>();
case 0xaa: return op_set_addr_bit();
case 0xab: return op_adjust_dp<&SMPcore::op_inc>();
case 0xac: return op_adjust_addr<&SMPcore::op_inc>();
case 0xad: return op_read_const<&SMPcore::op_cmp>(regs.y);
case 0xae: return op_pull(regs.a);
case 0xaf: return op_sta_ixinc();
case 0xb0: return op_branch(regs.p.c == 1);
case 0xb1: return op_jst();
case 0xb2: return op_set_bit();
case 0xb3: return op_branch_bit();
case 0xb4: return op_read_dpi<&SMPcore::op_sbc>(regs.a, regs.x);
case 0xb5: return op_read_addri<&SMPcore::op_sbc>(regs.x);
case 0xb6: return op_read_addri<&SMPcore::op_sbc>(regs.y);
case 0xb7: return op_read_idpy<&SMPcore::op_sbc>();
case 0xb8: return op_write_dp_const<&SMPcore::op_sbc>();
case 0xb9: return op_write_ix_iy<&SMPcore::op_sbc>();
case 0xba: return op_read_dpw<&SMPcore::op_ldw>();
case 0xbb: return op_adjust_dpx<&SMPcore::op_inc>();
case 0xbc: return op_adjust<&SMPcore::op_inc>(regs.a);
case 0xbd: return op_transfer(regs.x, regs.s);
case 0xbe: return op_das();
case 0xbf: return op_lda_ixinc();
case 0xc0: return op_set_flag(regs.p.i, 0);
case 0xc1: return op_jst();
case 0xc2: return op_set_bit();
case 0xc3: return op_branch_bit();
case 0xc4: return op_write_dp(regs.a);
case 0xc5: return op_write_addr(regs.a);
case 0xc6: return op_sta_ix();
case 0xc7: return op_sta_idpx();
case 0xc8: return op_read_const<&SMPcore::op_cmp>(regs.x);
case 0xc9: return op_write_addr(regs.x);
case 0xca: return op_set_addr_bit();
case 0xcb: return op_write_dp(regs.y);
case 0xcc: return op_write_addr(regs.y);
case 0xcd: return op_read_const<&SMPcore::op_ld>(regs.x);
case 0xce: return op_pull(regs.x);
case 0xcf: return op_mul_ya();
case 0xd0: return op_branch(regs.p.z == 0);
case 0xd1: return op_jst();
case 0xd2: return op_set_bit();
case 0xd3: return op_branch_bit();
case 0xd4: return op_write_dpi(regs.a, regs.x);
case 0xd5: return op_write_addri(regs.x);
case 0xd6: return op_write_addri(regs.y);
case 0xd7: return op_sta_idpy();
case 0xd8: return op_write_dp(regs.x);
case 0xd9: return op_write_dpi(regs.x, regs.y);
case 0xda: return op_stw_dp();
case 0xdb: return op_write_dpi(regs.y, regs.x);
case 0xdc: return op_adjust<&SMPcore::op_dec>(regs.y);
case 0xdd: return op_transfer(regs.y, regs.a);
case 0xde: return op_bne_dpx();
case 0xdf: return op_daa();
case 0xe0: return op_clv();
case 0xe1: return op_jst();
case 0xe2: return op_set_bit();
case 0xe3: return op_branch_bit();
case 0xe4: return op_read_dp<&SMPcore::op_ld>(regs.a);
case 0xe5: return op_read_addr<&SMPcore::op_ld>(regs.a);
case 0xe6: return op_read_ix<&SMPcore::op_ld>();
case 0xe7: return op_read_idpx<&SMPcore::op_ld>();
case 0xe8: return op_read_const<&SMPcore::op_ld>(regs.a);
case 0xe9: return op_read_addr<&SMPcore::op_ld>(regs.x);
case 0xea: return op_set_addr_bit();
case 0xeb: return op_read_dp<&SMPcore::op_ld>(regs.y);
case 0xec: return op_read_addr<&SMPcore::op_ld>(regs.y);
case 0xed: return op_cmc();
case 0xee: return op_pull(regs.y);
case 0xef: return op_wait();
case 0xf0: return op_branch(regs.p.z == 1);
case 0xf1: return op_jst();
case 0xf2: return op_set_bit();
case 0xf3: return op_branch_bit();
case 0xf4: return op_read_dpi<&SMPcore::op_ld>(regs.a, regs.x);
case 0xf5: return op_read_addri<&SMPcore::op_ld>(regs.x);
case 0xf6: return op_read_addri<&SMPcore::op_ld>(regs.y);
case 0xf7: return op_read_idpy<&SMPcore::op_ld>();
case 0xf8: return op_read_dp<&SMPcore::op_ld>(regs.x);
case 0xf9: return op_read_dpi<&SMPcore::op_ld>(regs.x, regs.y);
case 0xfa: return op_write_dp_dp<&SMPcore::op_st>();
case 0xfb: return op_read_dpi<&SMPcore::op_ld>(regs.y, regs.x);
case 0xfc: return op_adjust<&SMPcore::op_inc>(regs.y);
case 0xfd: return op_transfer(regs.a, regs.y);
case 0xfe: return op_bne_ydec();
case 0xff: return op_wait();
}
}
*/
}
#include "algorithms.cpp"
#include "opcodes.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"
void SMPcore::op_step() {
switch(opcode = op_readpc()) {
case 0x00: return op_nop();
case 0x01: return op_jst();
case 0x02: return op_set_bit();
case 0x03: return op_branch_bit();
case 0x04: return op_read_dp<&SMPcore::op_or>(regs.a);
case 0x05: return op_read_addr<&SMPcore::op_or>(regs.a);
case 0x06: return op_read_ix<&SMPcore::op_or>();
case 0x07: return op_read_idpx<&SMPcore::op_or>();
case 0x08: return op_read_const<&SMPcore::op_or>(regs.a);
case 0x09: return op_write_dp_dp<&SMPcore::op_or>();
case 0x0a: return op_set_addr_bit();
case 0x0b: return op_adjust_dp<&SMPcore::op_asl>();
case 0x0c: return op_adjust_addr<&SMPcore::op_asl>();
case 0x0d: return op_push(regs.p);
case 0x0e: return op_test_addr(1);
case 0x0f: return op_brk();
case 0x10: return op_branch(regs.p.n == 0);
case 0x11: return op_jst();
case 0x12: return op_set_bit();
case 0x13: return op_branch_bit();
case 0x14: return op_read_dpi<&SMPcore::op_or>(regs.a, regs.x);
case 0x15: return op_read_addri<&SMPcore::op_or>(regs.x);
case 0x16: return op_read_addri<&SMPcore::op_or>(regs.y);
case 0x17: return op_read_idpy<&SMPcore::op_or>();
case 0x18: return op_write_dp_const<&SMPcore::op_or>();
case 0x19: return op_write_ix_iy<&SMPcore::op_or>();
case 0x1a: return op_adjust_dpw(-1);
case 0x1b: return op_adjust_dpx<&SMPcore::op_asl>();
case 0x1c: return op_adjust<&SMPcore::op_asl>(regs.a);
case 0x1d: return op_adjust<&SMPcore::op_dec>(regs.x);
case 0x1e: return op_read_addr<&SMPcore::op_cmp>(regs.x);
case 0x1f: return op_jmp_iaddrx();
case 0x20: return op_set_flag(regs.p.p, 0);
case 0x21: return op_jst();
case 0x22: return op_set_bit();
case 0x23: return op_branch_bit();
case 0x24: return op_read_dp<&SMPcore::op_and>(regs.a);
case 0x25: return op_read_addr<&SMPcore::op_and>(regs.a);
case 0x26: return op_read_ix<&SMPcore::op_and>();
case 0x27: return op_read_idpx<&SMPcore::op_and>();
case 0x28: return op_read_const<&SMPcore::op_and>(regs.a);
case 0x29: return op_write_dp_dp<&SMPcore::op_and>();
case 0x2a: return op_set_addr_bit();
case 0x2b: return op_adjust_dp<&SMPcore::op_rol>();
case 0x2c: return op_adjust_addr<&SMPcore::op_rol>();
case 0x2d: return op_push(regs.a);
case 0x2e: return op_bne_dp();
case 0x2f: return op_branch(true);
case 0x30: return op_branch(regs.p.n == 1);
case 0x31: return op_jst();
case 0x32: return op_set_bit();
case 0x33: return op_branch_bit();
case 0x34: return op_read_dpi<&SMPcore::op_and>(regs.a, regs.x);
case 0x35: return op_read_addri<&SMPcore::op_and>(regs.x);
case 0x36: return op_read_addri<&SMPcore::op_and>(regs.y);
case 0x37: return op_read_idpy<&SMPcore::op_and>();
case 0x38: return op_write_dp_const<&SMPcore::op_and>();
case 0x39: return op_write_ix_iy<&SMPcore::op_and>();
case 0x3a: return op_adjust_dpw(+1);
case 0x3b: return op_adjust_dpx<&SMPcore::op_rol>();
case 0x3c: return op_adjust<&SMPcore::op_rol>(regs.a);
case 0x3d: return op_adjust<&SMPcore::op_inc>(regs.x);
case 0x3e: return op_read_dp<&SMPcore::op_cmp>(regs.x);
case 0x3f: return op_jsr_addr();
case 0x40: return op_set_flag(regs.p.p, 1);
case 0x41: return op_jst();
case 0x42: return op_set_bit();
case 0x43: return op_branch_bit();
case 0x44: return op_read_dp<&SMPcore::op_eor>(regs.a);
case 0x45: return op_read_addr<&SMPcore::op_eor>(regs.a);
case 0x46: return op_read_ix<&SMPcore::op_eor>();
case 0x47: return op_read_idpx<&SMPcore::op_eor>();
case 0x48: return op_read_const<&SMPcore::op_eor>(regs.a);
case 0x49: return op_write_dp_dp<&SMPcore::op_eor>();
case 0x4a: return op_set_addr_bit();
case 0x4b: return op_adjust_dp<&SMPcore::op_lsr>();
case 0x4c: return op_adjust_addr<&SMPcore::op_lsr>();
case 0x4d: return op_push(regs.x);
case 0x4e: return op_test_addr(0);
case 0x4f: return op_jsp_dp();
case 0x50: return op_branch(regs.p.v == 0);
case 0x51: return op_jst();
case 0x52: return op_set_bit();
case 0x53: return op_branch_bit();
case 0x54: return op_read_dpi<&SMPcore::op_eor>(regs.a, regs.x);
case 0x55: return op_read_addri<&SMPcore::op_eor>(regs.x);
case 0x56: return op_read_addri<&SMPcore::op_eor>(regs.y);
case 0x57: return op_read_idpy<&SMPcore::op_eor>();
case 0x58: return op_write_dp_const<&SMPcore::op_eor>();
case 0x59: return op_write_ix_iy<&SMPcore::op_eor>();
case 0x5a: return op_read_dpw<&SMPcore::op_cpw>();
case 0x5b: return op_adjust_dpx<&SMPcore::op_lsr>();
case 0x5c: return op_adjust<&SMPcore::op_lsr>(regs.a);
case 0x5d: return op_transfer(regs.a, regs.x);
case 0x5e: return op_read_addr<&SMPcore::op_cmp>(regs.y);
case 0x5f: return op_jmp_addr();
case 0x60: return op_set_flag(regs.p.c, 0);
case 0x61: return op_jst();
case 0x62: return op_set_bit();
case 0x63: return op_branch_bit();
case 0x64: return op_read_dp<&SMPcore::op_cmp>(regs.a);
case 0x65: return op_read_addr<&SMPcore::op_cmp>(regs.a);
case 0x66: return op_read_ix<&SMPcore::op_cmp>();
case 0x67: return op_read_idpx<&SMPcore::op_cmp>();
case 0x68: return op_read_const<&SMPcore::op_cmp>(regs.a);
case 0x69: return op_write_dp_dp<&SMPcore::op_cmp>();
case 0x6a: return op_set_addr_bit();
case 0x6b: return op_adjust_dp<&SMPcore::op_ror>();
case 0x6c: return op_adjust_addr<&SMPcore::op_ror>();
case 0x6d: return op_push(regs.y);
case 0x6e: return op_bne_dpdec();
case 0x6f: return op_rts();
case 0x70: return op_branch(regs.p.v == 1);
case 0x71: return op_jst();
case 0x72: return op_set_bit();
case 0x73: return op_branch_bit();
case 0x74: return op_read_dpi<&SMPcore::op_cmp>(regs.a, regs.x);
case 0x75: return op_read_addri<&SMPcore::op_cmp>(regs.x);
case 0x76: return op_read_addri<&SMPcore::op_cmp>(regs.y);
case 0x77: return op_read_idpy<&SMPcore::op_cmp>();
case 0x78: return op_write_dp_const<&SMPcore::op_cmp>();
case 0x79: return op_write_ix_iy<&SMPcore::op_cmp>();
case 0x7a: return op_read_dpw<&SMPcore::op_adw>();
case 0x7b: return op_adjust_dpx<&SMPcore::op_ror>();
case 0x7c: return op_adjust<&SMPcore::op_ror>(regs.a);
case 0x7d: return op_transfer(regs.x, regs.a);
case 0x7e: return op_read_dp<&SMPcore::op_cmp>(regs.y);
case 0x7f: return op_rti();
case 0x80: return op_set_flag(regs.p.c, 1);
case 0x81: return op_jst();
case 0x82: return op_set_bit();
case 0x83: return op_branch_bit();
case 0x84: return op_read_dp<&SMPcore::op_adc>(regs.a);
case 0x85: return op_read_addr<&SMPcore::op_adc>(regs.a);
case 0x86: return op_read_ix<&SMPcore::op_adc>();
case 0x87: return op_read_idpx<&SMPcore::op_adc>();
case 0x88: return op_read_const<&SMPcore::op_adc>(regs.a);
case 0x89: return op_write_dp_dp<&SMPcore::op_adc>();
case 0x8a: return op_set_addr_bit();
case 0x8b: return op_adjust_dp<&SMPcore::op_dec>();
case 0x8c: return op_adjust_addr<&SMPcore::op_dec>();
case 0x8d: return op_read_const<&SMPcore::op_ld>(regs.y);
case 0x8e: return op_plp();
case 0x8f: return op_write_dp_const<&SMPcore::op_st>();
case 0x90: return op_branch(regs.p.c == 0);
case 0x91: return op_jst();
case 0x92: return op_set_bit();
case 0x93: return op_branch_bit();
case 0x94: return op_read_dpi<&SMPcore::op_adc>(regs.a, regs.x);
case 0x95: return op_read_addri<&SMPcore::op_adc>(regs.x);
case 0x96: return op_read_addri<&SMPcore::op_adc>(regs.y);
case 0x97: return op_read_idpy<&SMPcore::op_adc>();
case 0x98: return op_write_dp_const<&SMPcore::op_adc>();
case 0x99: return op_write_ix_iy<&SMPcore::op_adc>();
case 0x9a: return op_read_dpw<&SMPcore::op_sbw>();
case 0x9b: return op_adjust_dpx<&SMPcore::op_dec>();
case 0x9c: return op_adjust<&SMPcore::op_dec>(regs.a);
case 0x9d: return op_transfer(regs.s, regs.x);
case 0x9e: return op_div_ya_x();
case 0x9f: return op_xcn();
case 0xa0: return op_set_flag(regs.p.i, 1);
case 0xa1: return op_jst();
case 0xa2: return op_set_bit();
case 0xa3: return op_branch_bit();
case 0xa4: return op_read_dp<&SMPcore::op_sbc>(regs.a);
case 0xa5: return op_read_addr<&SMPcore::op_sbc>(regs.a);
case 0xa6: return op_read_ix<&SMPcore::op_sbc>();
case 0xa7: return op_read_idpx<&SMPcore::op_sbc>();
case 0xa8: return op_read_const<&SMPcore::op_sbc>(regs.a);
case 0xa9: return op_write_dp_dp<&SMPcore::op_sbc>();
case 0xaa: return op_set_addr_bit();
case 0xab: return op_adjust_dp<&SMPcore::op_inc>();
case 0xac: return op_adjust_addr<&SMPcore::op_inc>();
case 0xad: return op_read_const<&SMPcore::op_cmp>(regs.y);
case 0xae: return op_pull(regs.a);
case 0xaf: return op_sta_ixinc();
case 0xb0: return op_branch(regs.p.c == 1);
case 0xb1: return op_jst();
case 0xb2: return op_set_bit();
case 0xb3: return op_branch_bit();
case 0xb4: return op_read_dpi<&SMPcore::op_sbc>(regs.a, regs.x);
case 0xb5: return op_read_addri<&SMPcore::op_sbc>(regs.x);
case 0xb6: return op_read_addri<&SMPcore::op_sbc>(regs.y);
case 0xb7: return op_read_idpy<&SMPcore::op_sbc>();
case 0xb8: return op_write_dp_const<&SMPcore::op_sbc>();
case 0xb9: return op_write_ix_iy<&SMPcore::op_sbc>();
case 0xba: return op_read_dpw<&SMPcore::op_ldw>();
case 0xbb: return op_adjust_dpx<&SMPcore::op_inc>();
case 0xbc: return op_adjust<&SMPcore::op_inc>(regs.a);
case 0xbd: return op_transfer(regs.x, regs.s);
case 0xbe: return op_das();
case 0xbf: return op_lda_ixinc();
case 0xc0: return op_set_flag(regs.p.i, 0);
case 0xc1: return op_jst();
case 0xc2: return op_set_bit();
case 0xc3: return op_branch_bit();
case 0xc4: return op_write_dp(regs.a);
case 0xc5: return op_write_addr(regs.a);
case 0xc6: return op_sta_ix();
case 0xc7: return op_sta_idpx();
case 0xc8: return op_read_const<&SMPcore::op_cmp>(regs.x);
case 0xc9: return op_write_addr(regs.x);
case 0xca: return op_set_addr_bit();
case 0xcb: return op_write_dp(regs.y);
case 0xcc: return op_write_addr(regs.y);
case 0xcd: return op_read_const<&SMPcore::op_ld>(regs.x);
case 0xce: return op_pull(regs.x);
case 0xcf: return op_mul_ya();
case 0xd0: return op_branch(regs.p.z == 0);
case 0xd1: return op_jst();
case 0xd2: return op_set_bit();
case 0xd3: return op_branch_bit();
case 0xd4: return op_write_dpi(regs.a, regs.x);
case 0xd5: return op_write_addri(regs.x);
case 0xd6: return op_write_addri(regs.y);
case 0xd7: return op_sta_idpy();
case 0xd8: return op_write_dp(regs.x);
case 0xd9: return op_write_dpi(regs.x, regs.y);
case 0xda: return op_stw_dp();
case 0xdb: return op_write_dpi(regs.y, regs.x);
case 0xdc: return op_adjust<&SMPcore::op_dec>(regs.y);
case 0xdd: return op_transfer(regs.y, regs.a);
case 0xde: return op_bne_dpx();
case 0xdf: return op_daa();
case 0xe0: return op_clv();
case 0xe1: return op_jst();
case 0xe2: return op_set_bit();
case 0xe3: return op_branch_bit();
case 0xe4: return op_read_dp<&SMPcore::op_ld>(regs.a);
case 0xe5: return op_read_addr<&SMPcore::op_ld>(regs.a);
case 0xe6: return op_read_ix<&SMPcore::op_ld>();
case 0xe7: return op_read_idpx<&SMPcore::op_ld>();
case 0xe8: return op_read_const<&SMPcore::op_ld>(regs.a);
case 0xe9: return op_read_addr<&SMPcore::op_ld>(regs.x);
case 0xea: return op_set_addr_bit();
case 0xeb: return op_read_dp<&SMPcore::op_ld>(regs.y);
case 0xec: return op_read_addr<&SMPcore::op_ld>(regs.y);
case 0xed: return op_cmc();
case 0xee: return op_pull(regs.y);
case 0xef: return op_wait();
case 0xf0: return op_branch(regs.p.z == 1);
case 0xf1: return op_jst();
case 0xf2: return op_set_bit();
case 0xf3: return op_branch_bit();
case 0xf4: return op_read_dpi<&SMPcore::op_ld>(regs.a, regs.x);
case 0xf5: return op_read_addri<&SMPcore::op_ld>(regs.x);
case 0xf6: return op_read_addri<&SMPcore::op_ld>(regs.y);
case 0xf7: return op_read_idpy<&SMPcore::op_ld>();
case 0xf8: return op_read_dp<&SMPcore::op_ld>(regs.x);
case 0xf9: return op_read_dpi<&SMPcore::op_ld>(regs.x, regs.y);
case 0xfa: return op_write_dp_dp<&SMPcore::op_st>();
case 0xfb: return op_read_dpi<&SMPcore::op_ld>(regs.y, regs.x);
case 0xfc: return op_adjust<&SMPcore::op_inc>(regs.y);
case 0xfd: return op_transfer(regs.a, regs.y);
case 0xfe: return op_bne_ydec();
case 0xff: return op_wait();
}
}
}

View File

@ -1,98 +1,96 @@
struct SMPcore {
virtual void op_io() = 0;
virtual uint8 op_read(uint16 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
void op_step();
#include "registers.hpp"
#include "memory.hpp"
regs_t regs;
word_t dp, sp, rd, wr, bit, ya;
struct SMPcore {
virtual void op_io() = 0;
virtual uint8 op_read(uint16 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
void op_step();
#include "registers.hpp"
#include "memory.hpp"
regs_t regs;
word_t dp, sp, rd, wr, bit, ya;
uint8 opcode;
int uindex;
void core_serialize(serializer&);
string disassemble_opcode(uint16 addr);
protected:
uint8 op_adc(uint8, uint8);
uint8 op_and(uint8, uint8);
uint8 op_asl(uint8);
uint8 op_cmp(uint8, uint8);
uint8 op_dec(uint8);
uint8 op_eor(uint8, uint8);
uint8 op_inc(uint8);
uint8 op_ld (uint8, uint8);
uint8 op_lsr(uint8);
uint8 op_or (uint8, uint8);
uint8 op_rol(uint8);
uint8 op_ror(uint8);
uint8 op_sbc(uint8, uint8);
uint8 op_st (uint8, uint8);
uint16 op_adw(uint16, uint16);
uint16 op_cpw(uint16, uint16);
uint16 op_ldw(uint16, uint16);
uint16 op_sbw(uint16, uint16);
template<uint8 (SMPcore::*op)(uint8)> void op_adjust(uint8&);
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_addr();
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_dp();
void op_adjust_dpw(signed);
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_dpx();
void op_branch(bool);
void op_branch_bit();
void op_pull(uint8&);
void op_push(uint8);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_addr(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_addri(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_const(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_dp(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_dpi(uint8&, uint8&);
template<uint16 (SMPcore::*op)(uint16, uint16)> void op_read_dpw();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_idpx();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_idpy();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_ix();
void op_set_addr_bit();
void op_set_bit();
void op_set_flag(bool&, bool);
void op_test_addr(bool);
void op_transfer(uint8&, uint8&);
void op_write_addr(uint8&);
void op_write_addri(uint8&);
void op_write_dp(uint8&);
void op_write_dpi(uint8&, uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_dp_const();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_dp_dp();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_ix_iy();
void op_bne_dp();
void op_bne_dpdec();
void op_bne_dpx();
void op_bne_ydec();
void op_brk();
void op_clv();
void op_cmc();
void op_daa();
void op_das();
void op_div_ya_x();
void op_jmp_addr();
void op_jmp_iaddrx();
void op_jsp_dp();
void op_jsr_addr();
void op_jst();
void op_lda_ixinc();
void op_mul_ya();
void op_nop();
void op_plp();
void op_rti();
void op_rts();
void op_sta_idpx();
void op_sta_idpy();
void op_sta_ix();
void op_sta_ixinc();
void op_stw_dp();
void op_wait();
void op_xcn();
};
void core_serialize(serializer&);
string disassemble_opcode(uint16 addr);
protected:
uint8 op_adc(uint8, uint8);
uint8 op_and(uint8, uint8);
uint8 op_asl(uint8);
uint8 op_cmp(uint8, uint8);
uint8 op_dec(uint8);
uint8 op_eor(uint8, uint8);
uint8 op_inc(uint8);
uint8 op_ld (uint8, uint8);
uint8 op_lsr(uint8);
uint8 op_or (uint8, uint8);
uint8 op_rol(uint8);
uint8 op_ror(uint8);
uint8 op_sbc(uint8, uint8);
uint8 op_st (uint8, uint8);
uint16 op_adw(uint16, uint16);
uint16 op_cpw(uint16, uint16);
uint16 op_ldw(uint16, uint16);
uint16 op_sbw(uint16, uint16);
template<uint8 (SMPcore::*op)(uint8)> void op_adjust(uint8&);
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_addr();
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_dp();
void op_adjust_dpw(signed);
template<uint8 (SMPcore::*op)(uint8)> void op_adjust_dpx();
void op_branch(bool);
void op_branch_bit();
void op_pull(uint8&);
void op_push(uint8);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_addr(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_addri(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_const(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_dp(uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_dpi(uint8&, uint8&);
template<uint16 (SMPcore::*op)(uint16, uint16)> void op_read_dpw();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_idpx();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_idpy();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_read_ix();
void op_set_addr_bit();
void op_set_bit();
void op_set_flag(bool&, bool);
void op_test_addr(bool);
void op_transfer(uint8&, uint8&);
void op_write_addr(uint8&);
void op_write_addri(uint8&);
void op_write_dp(uint8&);
void op_write_dpi(uint8&, uint8&);
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_dp_const();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_dp_dp();
template<uint8 (SMPcore::*op)(uint8, uint8)> void op_write_ix_iy();
void op_bne_dp();
void op_bne_dpdec();
void op_bne_dpx();
void op_bne_ydec();
void op_brk();
void op_clv();
void op_cmc();
void op_daa();
void op_das();
void op_div_ya_x();
void op_jmp_addr();
void op_jmp_iaddrx();
void op_jsp_dp();
void op_jsr_addr();
void op_jst();
void op_lda_ixinc();
void op_mul_ya();
void op_nop();
void op_plp();
void op_rti();
void op_rts();
void op_sta_idpx();
void op_sta_idpy();
void op_sta_ix();
void op_sta_ixinc();
void op_stw_dp();
void op_wait();
void op_xcn();
};

View File

@ -20,10 +20,10 @@ alwaysinline uint8 op_readdp(uint8 addr) {
alwaysinline void op_writedp(uint8 addr, uint8 data) {
return op_write((regs.p.p << 8) + addr, data);
}
alwaysinline void op_next() {
opcode = op_readpcfirst();
uindex = -1;
}
}
alwaysinline void op_next() {
opcode = op_readpcfirst();
uindex = -1;
}

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

@ -1,29 +1,27 @@
#ifdef SMPCORE_CPP
void SMPcore::core_serialize(serializer &s) {
s.integer(regs.pc);
s.integer(regs.a);
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.s);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.p);
s.integer(regs.p.b);
s.integer(regs.p.h);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(opcode);
s.integer(dp.w);
s.integer(sp.w);
s.integer(rd.w);
s.integer(wr.w);
s.integer(bit.w);
s.integer(ya.w);
#ifdef SMPCORE_CPP
s.integer(uindex);
}
#endif
void SMPcore::core_serialize(serializer &s) {
s.integer(regs.pc);
s.integer(regs.a);
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.s);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.p);
s.integer(regs.p.b);
s.integer(regs.p.h);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(opcode);
s.integer(dp.w);
s.integer(sp.w);
s.integer(rd.w);
s.integer(wr.w);
s.integer(bit.w);
s.integer(ya.w);
}
#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

@ -16,23 +16,12 @@ void SMP::step(unsigned clocks) {
}
void SMP::synchronize_cpu() {
if(CPU::Threaded == true) {
if(CPU::Threaded == true) {
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
} else {
while(clock >= 0) cpu.enter();
}
}
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) {
@ -45,17 +34,10 @@ void SMP::synchronize_dsp() {
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
}
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
}
debugger.op_exec(regs.pc);
if(interface()->wanttrace & TRACE_SMP_MASK)
@ -81,11 +63,7 @@ void SMP::power() {
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.pc = 0xffc0;
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;

View File

@ -1,63 +1,62 @@
struct SMP : public Processor, public SMPcore {
static const uint8 iplrom[64];
uint8* apuram; //[64 * 1024];
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
struct SMP : public Processor, public SMPcore {
static const uint8 iplrom[64];
uint8* apuram; //[64 * 1024];
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;
void port_write(uint2 port, uint8 data);
void enter();
void power();
void reset();
void serialize(serializer&);
SMP();
~SMP();
void initialize();
privileged:
#include "memory/memory.hpp"
#include "timing/timing.hpp"
struct {
//timing
unsigned clock_counter;
unsigned dsp_counter;
unsigned timer_step;
//$00f0
uint8 clock_speed;
uint8 timer_speed;
bool timers_enable;
bool ram_disable;
bool ram_writable;
bool timers_disable;
//$00f1
bool iplrom_enable;
//$00f2
uint8 dsp_addr;
//$00f8,$00f9
uint8 ram00f8;
uint8 ram00f9;
} status;
static void Enter();
friend class SMPcore;
struct Debugger {
hook<void (uint16)> op_exec;
hook<void (uint16)> op_read;
hook<void (uint16, uint8)> op_write;
} debugger;
};
extern SMP smp;
alwaysinline void synchronize_dsp();
uint8 port_read(uint2 port) const;
void port_write(uint2 port, uint8 data);
void enter();
void power();
void reset();
void serialize(serializer&);
SMP();
~SMP();
void initialize();
privileged:
#include "memory/memory.hpp"
#include "timing/timing.hpp"
struct {
//timing
unsigned clock_counter;
unsigned dsp_counter;
unsigned timer_step;
//$00f0
uint8 clock_speed;
uint8 timer_speed;
bool timers_enable;
bool ram_disable;
bool ram_writable;
bool timers_disable;
//$00f1
bool iplrom_enable;
//$00f2
uint8 dsp_addr;
//$00f8,$00f9
uint8 ram00f8;
uint8 ram00f9;
} status;
static void Enter();
friend class SMPcore;
struct Debugger {
hook<void (uint16)> op_exec;
hook<void (uint16)> op_read;
hook<void (uint16, uint8)> op_write;
} debugger;
};
extern SMP smp;

View File

@ -1,72 +1,62 @@
#ifdef SMP_CPP
void SMP::add_clocks(unsigned clocks) {
step(clocks);
synchronize_dsp();
#ifdef SMP_CPP
void SMP::add_clocks(unsigned clocks) {
step(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
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();
#endif
}
void SMP::cycle_edge() {
timer0.tick();
timer1.tick();
timer2.tick();
//TEST register S-SMP speed control
//24 clocks have already been added for this cycle at this point
switch(status.clock_speed) {
case 0: break; //100% speed
case 1: add_clocks(24); break; // 50% speed
case 2: while(true) add_clocks(24); // 0% speed -- locks S-SMP
case 3: add_clocks(24 * 9); break; // 10% speed
}
}
template<unsigned timer_frequency>
void SMP::Timer<timer_frequency>::tick() {
//stage 0 increment
stage0_ticks += smp.status.timer_step;
if(stage0_ticks < timer_frequency) return;
stage0_ticks -= timer_frequency;
//stage 1 increment
stage1_ticks ^= 1;
synchronize_stage1();
}
template<unsigned timer_frequency>
void SMP::Timer<timer_frequency>::synchronize_stage1() {
bool new_line = stage1_ticks;
if(smp.status.timers_enable == false) new_line = false;
if(smp.status.timers_disable == true) new_line = false;
bool old_line = current_line;
current_line = new_line;
if(old_line != 1 || new_line != 0) return; //only pulse on 1->0 transition
//stage 2 increment
if(enable == false) return;
if(++stage2_ticks != target) return;
//stage 3 increment
stage2_ticks = 0;
stage3_ticks++;
}
#endif
if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu();
#endif
}
void SMP::cycle_edge() {
timer0.tick();
timer1.tick();
timer2.tick();
//TEST register S-SMP speed control
//24 clocks have already been added for this cycle at this point
switch(status.clock_speed) {
case 0: break; //100% speed
case 1: add_clocks(24); break; // 50% speed
case 2: while(true) add_clocks(24); // 0% speed -- locks S-SMP
case 3: add_clocks(24 * 9); break; // 10% speed
}
}
template<unsigned timer_frequency>
void SMP::Timer<timer_frequency>::tick() {
//stage 0 increment
stage0_ticks += smp.status.timer_step;
if(stage0_ticks < timer_frequency) return;
stage0_ticks -= timer_frequency;
//stage 1 increment
stage1_ticks ^= 1;
synchronize_stage1();
}
template<unsigned timer_frequency>
void SMP::Timer<timer_frequency>::synchronize_stage1() {
bool new_line = stage1_ticks;
if(smp.status.timers_enable == false) new_line = false;
if(smp.status.timers_disable == true) new_line = false;
bool old_line = current_line;
current_line = new_line;
if(old_line != 1 || new_line != 0) return; //only pulse on 1->0 transition
//stage 2 increment
if(enable == false) return;
if(++stage2_ticks != target) return;
//stage 3 increment
stage2_ticks = 0;
stage3_ticks++;
}
#endif