Update to v094r33 release.

byuu says:

Small WIP, just fixes the timings for GSU multiply.

However, the actual product may still be wrong when CLSR and MS0 are
both set. Since I wasn't 'corrupting' the value in said case before,
then this behavior can only be better than before.

Turned the (cache,memory)_access_timing into functions that compute the
values; and pulled "clockspeed" into GSU.

Also, I'm thinking it might be kind of pointless to have clockspeed at
all. Supposedly even the Mario Chip can run at 21.48MHz anyway.
Enforcing 10.74MHz mode seems kind of silly. If we change it to just be
a "default value for CLSR", then we can just inline the memory access
tests without the need for the access_timing functions (literally just
clsr?2:1 then)

Slight compilation bug: go to processor/gsu/registers.hpp:33 and add

    reg16_t() = default;

I missed it due to a partial recompile. Too lazy to upload another WIP
just for that.

Probably not worth doing much SuperFX testing just yet, as it looks like
they're doing some other tests at the moment on NESdev.
This commit is contained in:
Tim Allen
2015-06-27 12:38:47 +10:00
parent 169e400437
commit 4c9266d18f
22 changed files with 403 additions and 366 deletions

View File

@@ -2,11 +2,11 @@
//ROM / RAM access from the S-CPU
unsigned SuperFX::CPUROM::size() const {
auto SuperFX::CPUROM::size() const -> unsigned {
return superfx.rom.size();
}
uint8 SuperFX::CPUROM::read(unsigned addr) {
auto SuperFX::CPUROM::read(unsigned addr) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
static const uint8_t data[16] = {
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
@@ -17,20 +17,20 @@ uint8 SuperFX::CPUROM::read(unsigned addr) {
return superfx.rom.read(addr);
}
void SuperFX::CPUROM::write(unsigned addr, uint8 data) {
auto SuperFX::CPUROM::write(unsigned addr, uint8 data) -> void {
superfx.rom.write(addr, data);
}
unsigned SuperFX::CPURAM::size() const {
auto SuperFX::CPURAM::size() const -> unsigned {
return superfx.ram.size();
}
uint8 SuperFX::CPURAM::read(unsigned addr) {
auto SuperFX::CPURAM::read(unsigned addr) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return cpu.regs.mdr;
return superfx.ram.read(addr);
}
void SuperFX::CPURAM::write(unsigned addr, uint8 data) {
auto SuperFX::CPURAM::write(unsigned addr, uint8 data) -> void {
superfx.ram.write(addr, data);
}

View File

@@ -1,11 +1,11 @@
struct CPUROM : Memory {
unsigned size() const;
uint8 read(unsigned);
void write(unsigned, uint8);
auto size() const -> unsigned;
auto read(unsigned) -> uint8;
auto write(unsigned, uint8) -> void;
} cpurom;
struct CPURAM : Memory {
unsigned size() const;
uint8 read(unsigned);
void write(unsigned, uint8);
auto size() const -> unsigned;
auto read(unsigned) -> uint8;
auto write(unsigned, uint8) -> void;
} cpuram;

View File

@@ -1,16 +1,16 @@
#ifdef SUPERFX_CPP
void SuperFX::stop() {
auto SuperFX::stop() -> void {
cpu.regs.irq = 1;
}
uint8 SuperFX::color(uint8 source) {
auto SuperFX::color(uint8 source) -> uint8 {
if(regs.por.highnibble) return (regs.colr & 0xf0) | (source >> 4);
if(regs.por.freezehigh) return (regs.colr & 0xf0) | (source & 0x0f);
return source;
}
void SuperFX::plot(uint8 x, uint8 y) {
auto SuperFX::plot(uint8 x, uint8 y) -> void {
uint8 color = regs.colr;
if(regs.por.dither && regs.scmr.md != 3) {
@@ -48,7 +48,7 @@ void SuperFX::plot(uint8 x, uint8 y) {
}
}
uint8 SuperFX::rpix(uint8 x, uint8 y) {
auto SuperFX::rpix(uint8 x, uint8 y) -> uint8 {
pixelcache_flush(pixelcache[1]);
pixelcache_flush(pixelcache[0]);
@@ -66,14 +66,14 @@ uint8 SuperFX::rpix(uint8 x, uint8 y) {
for(unsigned n = 0; n < bpp; n++) {
unsigned byte = ((n >> 1) << 4) + (n & 1); // = [n]{ 0, 1, 16, 17, 32, 33, 48, 49 };
step(memory_access_speed);
step(memory_access_speed());
data |= ((bus_read(addr + byte) >> x) & 1) << n;
}
return data;
}
void SuperFX::pixelcache_flush(pixelcache_t& cache) {
auto SuperFX::pixelcache_flush(pixelcache_t& cache) -> void {
if(cache.bitpend == 0x00) return;
uint8 x = cache.offset << 3;
@@ -94,11 +94,11 @@ void SuperFX::pixelcache_flush(pixelcache_t& cache) {
uint8 data = 0x00;
for(unsigned x = 0; x < 8; x++) data |= ((cache.data[x] >> n) & 1) << x;
if(cache.bitpend != 0xff) {
step(memory_access_speed);
step(memory_access_speed());
data &= cache.bitpend;
data |= bus_read(addr + byte) & ~cache.bitpend;
}
step(memory_access_speed);
step(memory_access_speed());
bus_write(addr + byte, data);
}

View File

@@ -1,5 +1,5 @@
void stop();
uint8 color(uint8 source);
void plot(uint8 x, uint8 y);
uint8 rpix(uint8 x, uint8 y);
void pixelcache_flush(pixelcache_t& cache);
auto stop() -> void;
auto color(uint8 source) -> uint8;
auto plot(uint8 x, uint8 y) -> void;
auto rpix(uint8 x, uint8 y) -> uint8;
auto pixelcache_flush(pixelcache_t& cache) -> void;

View File

@@ -2,7 +2,7 @@
//TODO: this belongs in processor/gsu
void SuperFX::disassemble_opcode(char* output) {
auto SuperFX::disassemble_opcode(char* output) -> void {
*output = 0;
if(!regs.sfr.alt2) {
@@ -41,7 +41,7 @@ void SuperFX::disassemble_opcode(char* output) {
#define op1 bus_read((regs.pbr << 16) + regs.r[15] + 0)
#define op2 bus_read((regs.pbr << 16) + regs.r[15] + 1)
void SuperFX::disassemble_alt0(char* output) {
auto SuperFX::disassemble_alt0(char* output) -> void {
char t[256] = "";
switch(op0) {
case (0x00): sprintf(t, "stop"); break;
@@ -98,7 +98,7 @@ void SuperFX::disassemble_alt0(char* output) {
strcat(output, t);
}
void SuperFX::disassemble_alt1(char* output) {
auto SuperFX::disassemble_alt1(char* output) -> void {
char t[256] = "";
switch(op0) {
case (0x00): sprintf(t, "stop"); break;
@@ -155,7 +155,7 @@ void SuperFX::disassemble_alt1(char* output) {
strcat(output, t);
}
void SuperFX::disassemble_alt2(char* output) {
auto SuperFX::disassemble_alt2(char* output) -> void {
char t[256] = "";
switch(op0) {
case (0x00): sprintf(t, "stop"); break;
@@ -212,7 +212,7 @@ void SuperFX::disassemble_alt2(char* output) {
strcat(output, t);
}
void SuperFX::disassemble_alt3(char* output) {
auto SuperFX::disassemble_alt3(char* output) -> void {
char t[256] = "";
switch(op0) {
case (0x00): sprintf(t, "stop"); break;

View File

@@ -1,5 +1,5 @@
void disassemble_opcode(char* output);
void disassemble_alt0(char* output);
void disassemble_alt1(char* output);
void disassemble_alt2(char* output);
void disassemble_alt3(char* output);
auto disassemble_opcode(char* output) -> void;
auto disassemble_alt0(char* output) -> void;
auto disassemble_alt1(char* output) -> void;
auto disassemble_alt2(char* output) -> void;
auto disassemble_alt3(char* output) -> void;

View File

@@ -1,6 +1,6 @@
#ifdef SUPERFX_CPP
uint8 SuperFX::bus_read(unsigned addr) {
auto SuperFX::bus_read(unsigned addr) -> uint8 {
if((addr & 0xc00000) == 0x000000) { //$00-3f:0000-7fff, $00-3f:8000-ffff
while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6);
@@ -26,7 +26,7 @@ uint8 SuperFX::bus_read(unsigned addr) {
}
}
void SuperFX::bus_write(unsigned addr, uint8 data) {
auto SuperFX::bus_write(unsigned addr, uint8 data) -> void {
if((addr & 0xe00000) == 0x600000) { //$60-7f:0000-ffff
while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
step(6);
@@ -36,19 +36,19 @@ void SuperFX::bus_write(unsigned addr, uint8 data) {
}
}
uint8 SuperFX::op_read(uint16 addr) {
auto SuperFX::op_read(uint16 addr) -> uint8 {
uint16 offset = addr - regs.cbr;
if(offset < 512) {
if(cache.valid[offset >> 4] == false) {
unsigned dp = offset & 0xfff0;
unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
for(unsigned n = 0; n < 16; n++) {
step(memory_access_speed);
step(memory_access_speed());
cache.buffer[dp++] = bus_read(sp++);
}
cache.valid[offset >> 4] = true;
} else {
step(cache_access_speed);
step(cache_access_speed());
}
return cache.buffer[offset];
}
@@ -56,46 +56,46 @@ uint8 SuperFX::op_read(uint16 addr) {
if(regs.pbr <= 0x5f) {
//$[00-5f]:[0000-ffff] ROM
rombuffer_sync();
step(memory_access_speed);
step(memory_access_speed());
return bus_read((regs.pbr << 16) + addr);
} else {
//$[60-7f]:[0000-ffff] RAM
rambuffer_sync();
step(memory_access_speed);
step(memory_access_speed());
return bus_read((regs.pbr << 16) + addr);
}
}
uint8 SuperFX::peekpipe() {
auto SuperFX::peekpipe() -> uint8 {
uint8 result = regs.pipeline;
regs.pipeline = op_read(regs.r[15]);
r15_modified = false;
return result;
}
uint8 SuperFX::pipe() {
auto SuperFX::pipe() -> uint8 {
uint8 result = regs.pipeline;
regs.pipeline = op_read(++regs.r[15]);
r15_modified = false;
return result;
}
void SuperFX::cache_flush() {
auto SuperFX::cache_flush() -> void {
for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
}
uint8 SuperFX::cache_mmio_read(uint16 addr) {
auto SuperFX::cache_mmio_read(uint16 addr) -> uint8 {
addr = (addr + regs.cbr) & 511;
return cache.buffer[addr];
}
void SuperFX::cache_mmio_write(uint16 addr, uint8 data) {
auto SuperFX::cache_mmio_write(uint16 addr, uint8 data) -> void {
addr = (addr + regs.cbr) & 511;
cache.buffer[addr] = data;
if((addr & 15) == 15) cache.valid[addr >> 4] = true;
}
void SuperFX::memory_reset() {
auto SuperFX::memory_reset() -> void {
rom_mask = rom.size() - 1;
ram_mask = ram.size() - 1;

View File

@@ -1,14 +1,15 @@
unsigned rom_mask; //rom_size - 1
unsigned ram_mask; //ram_size - 1
uint8 bus_read(unsigned addr);
void bus_write(unsigned addr, uint8 data);
uint8 op_read(uint16 addr);
alwaysinline uint8 peekpipe();
alwaysinline uint8 pipe();
auto bus_read(unsigned addr) -> uint8;
auto bus_write(unsigned addr, uint8 data) -> void;
void cache_flush();
uint8 cache_mmio_read(uint16 addr);
void cache_mmio_write(uint16 addr, uint8 data);
auto op_read(uint16 addr) -> uint8;
alwaysinline auto peekpipe() -> uint8;
alwaysinline auto pipe() -> uint8;
void memory_reset();
auto cache_flush() -> void;
auto cache_mmio_read(uint16 addr) -> uint8;
auto cache_mmio_write(uint16 addr, uint8 data) -> void;
auto memory_reset() -> void;

View File

@@ -1,6 +1,6 @@
#ifdef SUPERFX_CPP
uint8 SuperFX::mmio_read(unsigned addr) {
auto SuperFX::mmio_read(unsigned addr) -> uint8 {
cpu.synchronize_coprocessors();
addr &= 0xffff;
@@ -52,7 +52,7 @@ uint8 SuperFX::mmio_read(unsigned addr) {
return 0x00;
}
void SuperFX::mmio_write(unsigned addr, uint8 data) {
auto SuperFX::mmio_write(unsigned addr, uint8 data) -> void {
cpu.synchronize_coprocessors();
addr &= 0xffff;
@@ -97,7 +97,6 @@ void SuperFX::mmio_write(unsigned addr, uint8 data) {
case 0x3037: {
regs.cfgr = data;
update_speed();
} break;
case 0x3038: {
@@ -106,7 +105,6 @@ void SuperFX::mmio_write(unsigned addr, uint8 data) {
case 0x3039: {
regs.clsr = data;
update_speed();
} break;
case 0x303a: {

View File

@@ -1,2 +1,2 @@
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
auto mmio_read(unsigned addr) -> uint8;
auto mmio_write(unsigned addr, uint8 data) -> void;

View File

@@ -1,16 +1,11 @@
#ifdef SUPERFX_CPP
void SuperFX::serialize(serializer& s) {
auto SuperFX::serialize(serializer& s) -> void {
GSU::serialize(s);
Thread::serialize(s);
s.array(ram.data(), ram.size());
s.integer(clockmode);
s.integer(instruction_counter);
s.integer(cache_access_speed);
s.integer(memory_access_speed);
s.integer(r15_modified);
}

View File

@@ -13,9 +13,11 @@ namespace SuperFamicom {
SuperFX superfx;
void SuperFX::Enter() { superfx.enter(); }
auto SuperFX::Enter() -> void {
superfx.enter();
}
void SuperFX::enter() {
auto SuperFX::enter() -> void {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
@@ -37,25 +39,25 @@ void SuperFX::enter() {
}
}
void SuperFX::init() {
auto SuperFX::init() -> void {
initialize_opcode_table();
regs.r[14].modify = {&SuperFX::r14_modify, this};
regs.r[15].modify = {&SuperFX::r15_modify, this};
}
void SuperFX::load() {
auto SuperFX::load() -> void {
}
void SuperFX::unload() {
auto SuperFX::unload() -> void {
rom.reset();
ram.reset();
}
void SuperFX::power() {
auto SuperFX::power() -> void {
GSU::power();
}
void SuperFX::reset() {
auto SuperFX::reset() -> void {
GSU::reset();
create(SuperFX::Enter, system.cpu_frequency());
instruction_counter = 0;

View File

@@ -9,18 +9,21 @@ struct SuperFX : Processor::GSU, Coprocessor {
#include "timing/timing.hpp"
#include "disassembler/disassembler.hpp"
static void Enter();
void enter();
void init();
void load();
void unload();
void power();
void reset();
void serialize(serializer&);
//superfx.cpp
static auto Enter() -> void;
auto enter() -> void;
auto init() -> void;
auto load() -> void;
auto unload() -> void;
auto power() -> void;
auto reset() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
privileged:
unsigned clockmode = 0; //0 = selectable, 1 = force 10.74mhz, 2 = force 21.48mhz
unsigned instruction_counter;
unsigned instruction_counter = 0;
};
extern SuperFX superfx;

View File

@@ -1,6 +1,6 @@
#ifdef SUPERFX_CPP
void SuperFX::step(unsigned clocks) {
auto SuperFX::step(unsigned clocks) -> void {
if(regs.romcl) {
regs.romcl -= min(clocks, regs.romcl);
if(regs.romcl == 0) {
@@ -20,70 +20,47 @@ void SuperFX::step(unsigned clocks) {
synchronize_cpu();
}
void SuperFX::rombuffer_sync() {
auto SuperFX::rombuffer_sync() -> void {
if(regs.romcl) step(regs.romcl);
}
void SuperFX::rombuffer_update() {
auto SuperFX::rombuffer_update() -> void {
regs.sfr.r = 1;
regs.romcl = memory_access_speed;
regs.romcl = memory_access_speed();
}
uint8 SuperFX::rombuffer_read() {
auto SuperFX::rombuffer_read() -> uint8 {
rombuffer_sync();
return regs.romdr;
}
void SuperFX::rambuffer_sync() {
auto SuperFX::rambuffer_sync() -> void {
if(regs.ramcl) step(regs.ramcl);
}
uint8 SuperFX::rambuffer_read(uint16 addr) {
auto SuperFX::rambuffer_read(uint16 addr) -> uint8 {
rambuffer_sync();
return bus_read(0x700000 + (regs.rambr << 16) + addr);
}
void SuperFX::rambuffer_write(uint16 addr, uint8 data) {
auto SuperFX::rambuffer_write(uint16 addr, uint8 data) -> void {
rambuffer_sync();
regs.ramcl = memory_access_speed;
regs.ramcl = memory_access_speed();
regs.ramar = addr;
regs.ramdr = data;
}
void SuperFX::r14_modify(uint16 data) {
auto SuperFX::r14_modify(uint16 data) -> void {
regs.r[14].data = data;
rombuffer_update();
}
void SuperFX::r15_modify(uint16 data) {
auto SuperFX::r15_modify(uint16 data) -> void {
regs.r[15].data = data;
r15_modified = true;
}
void SuperFX::update_speed() {
//force SuperFX1 mode?
if(clockmode == 1) {
cache_access_speed = 2;
memory_access_speed = 6;
return;
}
//force SuperFX2 mode?
if(clockmode == 2) {
cache_access_speed = 1;
memory_access_speed = 5;
regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
return;
}
//default: allow S-CPU to select mode
cache_access_speed = (regs.clsr ? 1 : 2);
memory_access_speed = (regs.clsr ? 5 : 6);
if(regs.clsr) regs.cfgr.ms0 = 0; //cannot use high-speed multiplication in 21MHz mode
}
void SuperFX::timing_reset() {
update_speed();
auto SuperFX::timing_reset() -> void {
r15_modified = false;
regs.romcl = 0;

View File

@@ -1,19 +1,16 @@
unsigned cache_access_speed;
unsigned memory_access_speed;
bool r15_modified;
bool r15_modified = false;
void step(unsigned clocks);
auto step(unsigned clocks) -> void;
void rombuffer_sync();
void rombuffer_update();
uint8 rombuffer_read();
auto rombuffer_sync() -> void;
auto rombuffer_update() -> void;
auto rombuffer_read() -> uint8;
void rambuffer_sync();
uint8 rambuffer_read(uint16 addr);
void rambuffer_write(uint16 addr, uint8 data);
auto rambuffer_sync() -> void;
auto rambuffer_read(uint16 addr) -> uint8;
auto rambuffer_write(uint16 addr, uint8 data) -> void;
void r14_modify(uint16);
void r15_modify(uint16);
auto r14_modify(uint16) -> void;
auto r15_modify(uint16) -> void;
void update_speed();
void timing_reset();
auto timing_reset() -> void;