Skip to content

Commit

Permalink
Update to v106r62 release.
Browse files Browse the repository at this point in the history
byuu says:

Changelog:

  - sfc/cx4: added missing instructions [info from Overload]
  - sfc/cx4: added instruction cache emulation [info from ikari]
  - sfc/sa1: don't let CPU access SA1-only I/O registers, and vice versa
  - sfc/sa1: fixed IRQs that were broken from the recent WIP
  - sfc/sa1: significantly improved bus conflict emulation
      - all tests match hardware now, other than HDMA ROM↔ROM, which
        is 0.5 - 0.8% too fast
  - sfc/cpu: fixed a bug with DMA→CPU alignment timing
  - sfc/cpu: removed the DMA pipe; performs writes on the same cycles as
    reads [info from nocash]
  - sfc/memory: fix a crashing bug due to not clearing Memory size field
    [hex_usr]
  - bsnes/gb: use .rtc for real-time clock file extensions on the Game
    Boy [hex_usr]
  - ruby/cgl: compilation fix [Sintendo]

Now let's see if I can accept being off by ~0.65% on one of twelve SA1
timing tests for the time being and prioritize much more important
things or not.
  • Loading branch information
Screwtapello committed Sep 10, 2018
1 parent 3d34517 commit c2d0ed4
Show file tree
Hide file tree
Showing 34 changed files with 1,450 additions and 795 deletions.
2 changes: 1 addition & 1 deletion higan/emulator/emulator.hpp
Expand Up @@ -28,7 +28,7 @@ using namespace nall;

namespace Emulator {
static const string Name = "higan";
static const string Version = "106.61";
static const string Version = "106.62";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";
Expand Down
44 changes: 23 additions & 21 deletions higan/processor/hg51b/hg51b.cpp
Expand Up @@ -4,6 +4,7 @@
namespace Processor {

#include "registers.cpp"
#include "instruction.cpp"
#include "instructions.cpp"
#include "serialization.cpp"

Expand All @@ -24,7 +25,7 @@ auto HG51B::wait(uint24 address) -> uint {
auto HG51B::main() -> void {
if(io.lock) return step(1);
if(io.suspend.enable) return suspend();
if(io.cache.enable) return cache();
if(io.cache.enable) return cache(), void();
if(io.dma.enable) return dma();
if(io.halt) return step(1);
return execute();
Expand All @@ -37,55 +38,56 @@ auto HG51B::step(uint clocks) -> void {
} else {
io.bus.enable = 0;
io.bus.pending = 0;
if(io.bus.reading) io.bus.reading = 0, r.busData = read(io.bus.address);
if(io.bus.writing) io.bus.writing = 0, write(io.bus.address, r.busData);
if(io.bus.reading) io.bus.reading = 0, r.mdr = read(io.bus.address);
if(io.bus.writing) io.bus.writing = 0, write(io.bus.address, r.mdr);
}
}
}

auto HG51B::execute() -> void {
uint24 address = io.cache.base + r.pb * 512;
if(io.cache.address[io.cache.page] != address) {
io.cache.page ^= 1;
if(io.cache.address[io.cache.page] != address) {
if(io.cache.lock[io.cache.page]) {
io.cache.page ^= 1;
if(io.cache.lock[io.cache.page]) return halt();
}
cache();
}
}

opcode = programRAM[io.cache.page][r.pc];
if(!cache()) return halt();
auto opcode = programRAM[io.cache.page][r.pc];
advance();

step(1);
instruction();
instructionTable[opcode]();
}

auto HG51B::advance() -> void {
if(++r.pc == 0) {
if(io.cache.page == 1) return halt();
io.cache.page = 1;
if(io.cache.lock[io.cache.page]) return halt();
r.pb = r.p;
if(!cache()) return halt();
}
}

auto HG51B::suspend() -> void {
if(!io.suspend.duration) return step(1); //indefinite
step(io.suspend.duration);
io.suspend.enable = 0;
io.suspend.duration = 0;
io.suspend.enable = 0;
}

auto HG51B::cache() -> void {
auto HG51B::cache() -> bool {
uint24 address = io.cache.base + r.pb * 512;

//try to use the current page ...
if(io.cache.address[io.cache.page] == address) return io.cache.enable = 0, true;
//if it's not valid, try to use the other page ...
io.cache.page ^= 1;
if(io.cache.address[io.cache.page] == address) return io.cache.enable = 0, true;
//if it's not valid, try to load into the other page ...
if(io.cache.lock[io.cache.page]) io.cache.page ^= 1;
//if it's locked, try to load into the first page ...
if(io.cache.lock[io.cache.page]) return io.cache.enable = 0, false;

io.cache.address[io.cache.page] = address;
for(uint offset : range(256)) {
step(wait(address)); programRAM[io.cache.page][offset].byte(0) = read(address++);
step(wait(address)); programRAM[io.cache.page][offset].byte(1) = read(address++);
}
io.cache.enable = 0;
return io.cache.enable = 0, true;
}

auto HG51B::dma() -> void {
Expand Down
124 changes: 97 additions & 27 deletions higan/processor/hg51b/hg51b.hpp
@@ -1,10 +1,14 @@
#pragma once

//Hitachi HG51B169 (HG51BS family/derivative?)
//Hitachi HG51B S169

namespace Processor {

struct HG51B {
//instruction.cpp
HG51B();

//hg51b.cpp
virtual auto step(uint clocks) -> void;
virtual auto isROM(uint24 address) -> bool = 0;
virtual auto isRAM(uint24 address) -> bool = 0;
Expand All @@ -17,49 +21,115 @@ struct HG51B {
auto execute() -> void;
auto advance() -> void;
auto suspend() -> void;
auto cache() -> void;
auto cache() -> bool;
auto dma() -> void;
auto running() const -> bool;
auto busy() const -> bool;

auto power() -> void;

//instructions.cpp
auto push() -> void;
auto pull() -> void;

auto algorithmADD(uint24 x, uint24 y) -> uint24;
auto algorithmAND(uint24 x, uint24 y) -> uint24;
auto algorithmASR(uint24 a, uint5 s) -> uint24;
auto algorithmMUL(int24 x, int24 y) -> uint48;
auto algorithmOR(uint24 x, uint24 y) -> uint24;
auto algorithmROR(uint24 a, uint5 s) -> uint24;
auto algorithmSHL(uint24 a, uint5 s) -> uint24;
auto algorithmSHR(uint24 a, uint5 s) -> uint24;
auto algorithmSUB(uint24 x, uint24 y) -> uint24;
auto algorithmSX(uint24 x) -> uint24;
auto algorithmXNOR(uint24 x, uint24 y) -> uint24;
auto algorithmXOR(uint24 x, uint24 y) -> uint24;

auto instructionADD(uint7 reg, uint5 shift) -> void;
auto instructionADD(uint8 imm, uint5 shift) -> void;
auto instructionAND(uint7 reg, uint5 shift) -> void;
auto instructionAND(uint8 imm, uint5 shift) -> void;
auto instructionASR(uint7 reg) -> void;
auto instructionASR(uint5 imm) -> void;
auto instructionCLEAR() -> void;
auto instructionCMP(uint7 reg, uint5 shift) -> void;
auto instructionCMP(uint8 imm, uint5 shift) -> void;
auto instructionCMPR(uint7 reg, uint5 shift) -> void;
auto instructionCMPR(uint8 imm, uint5 shift) -> void;
auto instructionHALT() -> void;
auto instructionINC(uint24& reg) -> void;
auto instructionJMP(uint8 data, uint1 far, const uint1& take) -> void;
auto instructionJSR(uint8 data, uint1 far, const uint1& take) -> void;
auto instructionLD(uint24& out, uint7 reg) -> void;
auto instructionLD(uint15& out, uint4 reg) -> void;
auto instructionLD(uint24& out, uint8 imm) -> void;
auto instructionLD(uint15& out, uint8 imm) -> void;
auto instructionLDL(uint15& out, uint8 imm) -> void;
auto instructionLDH(uint15& out, uint7 imm) -> void;
auto instructionMUL(uint7 reg) -> void;
auto instructionMUL(uint8 imm) -> void;
auto instructionNOP() -> void;
auto instructionOR(uint7 reg, uint5 shift) -> void;
auto instructionOR(uint8 imm, uint5 shift) -> void;
auto instructionRDRAM(uint2 byte, uint24& a) -> void;
auto instructionRDRAM(uint2 byte, uint8 imm) -> void;
auto instructionRDROM(uint24& reg) -> void;
auto instructionRDROM(uint10 imm) -> void;
auto instructionROR(uint7 reg) -> void;
auto instructionROR(uint5 imm) -> void;
auto instructionRTS() -> void;
auto instructionSHL(uint7 reg) -> void;
auto instructionSHL(uint5 imm) -> void;
auto instructionSHR(uint7 reg) -> void;
auto instructionSHR(uint5 imm) -> void;
auto instructionSKIP(uint1 take, const uint1& flag) -> void;
auto instructionST(uint7 reg, uint24& in) -> void;
auto instructionSUB(uint7 reg, uint5 shift) -> void;
auto instructionSUB(uint8 imm, uint5 shift) -> void;
auto instructionSUBR(uint7 reg, uint5 shift) -> void;
auto instructionSUBR(uint8 imm, uint5 shift) -> void;
auto instructionSWAP(uint24& a, uint4 reg) -> void;
auto instructionSXB() -> void;
auto instructionSXW() -> void;
auto instructionWAIT() -> void;
auto instructionWRRAM(uint2 byte, uint24& a) -> void;
auto instructionWRRAM(uint2 byte, uint8 imm) -> void;
auto instructionXNOR(uint7 reg, uint5 shift) -> void;
auto instructionXNOR(uint8 imm, uint5 shift) -> void;
auto instructionXOR(uint7 reg, uint5 shift) -> void;
auto instructionXOR(uint8 imm, uint5 shift) -> void;

//serialization.cpp
auto serialize(serializer&) -> void;

uint16 programRAM[2][256];
uint16 programRAM[2][256]; //instruction cache
uint24 dataROM[1024];
uint8 dataRAM[3072];

protected:
auto push() -> void;
auto pull() -> void;
auto sa() -> uint;
auto ri() -> uint;
auto np() -> void;
auto instruction() -> void;

//registers.cpp
auto readRegister(uint7 address) -> uint24;
auto writeRegister(uint7 address, uint24 data) -> void;

protected:
struct Registers {
uint16 p;
uint16 pb; //program bank
uint15 pb; //program bank
uint8 pc; //program counter

boolean n; //negative
boolean z; //zero
boolean c; //carry
boolean v; //overflow
boolean i; //interrupt

uint24 a; //accumulator
uint24 acch;
uint24 accl;
uint24 busData;
uint24 romData;
uint24 ramData;
uint24 busAddress;
uint24 ramAddress;
uint24 gpr[16];
uint24 a; //accumulator
uint15 p; //page register
uint48 mul; //multiplier
uint24 mdr; //bus memory data register
uint24 rom; //data ROM data buffer
uint24 ram; //data RAM data buffer
uint24 mar; //bus memory address register
uint24 dpr; //data RAM address pointer
uint24 gpr[16]; //general purpose registers
} r;

struct IO {
Expand All @@ -83,9 +153,9 @@ struct HG51B {
uint1 enable;
uint1 page;
uint1 lock[2];
uint24 address[2];
uint24 base;
uint16 pb;
uint24 address[2]; //cache address is in bytes; so 24-bit
uint24 base; //base address is also in bytes
uint15 pb;
uint8 pc;
} cache;

Expand All @@ -105,8 +175,8 @@ struct HG51B {
} bus;
} io;

uint24 stack[8];
uint16 opcode;
uint23 stack[8];
function<void ()> instructionTable[65536];
};

}

0 comments on commit c2d0ed4

Please sign in to comment.