Const some more bus/processor usage, and ensure the data bus is a member, not a reference to memory.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2018-06-10 00:40:56 +01:00
parent 7531f8a24a
commit 3e854c7c49
28 changed files with 358 additions and 151 deletions

View File

@ -12,8 +12,8 @@ namespace EightBit {
public:
Disassembler();
static std::string state(Intel8080& cpu);
std::string disassemble(Intel8080& cpu);
static std::string state(const Intel8080& cpu);
std::string disassemble(const Intel8080& cpu);
static std::string flag(uint8_t value, int flag, std::string represents, std::string off = "-");
static std::string flags(uint8_t value);
@ -26,7 +26,7 @@ namespace EightBit {
private:
mutable boost::format m_formatter;
void disassemble(std::ostringstream& output, Intel8080& cpu, uint16_t pc);
void disassemble(std::ostringstream& output, const Intel8080& cpu, uint16_t pc);
void disassemble(
std::ostringstream& output,

View File

@ -29,9 +29,13 @@ namespace EightBit {
virtual int execute(uint8_t opcode) final;
virtual int step() final;
virtual register16_t AF() const final;
virtual register16_t& AF() final;
virtual register16_t BC() const final;
virtual register16_t& BC() final;
virtual register16_t DE() const final;
virtual register16_t& DE() final;
virtual register16_t HL() const final;
virtual register16_t& HL() final;
protected:
@ -101,6 +105,21 @@ namespace EightBit {
}
}
register16_t RP(int rp) const {
switch (rp) {
case 0b00:
return BC();
case 0b01:
return DE();
case 0b10:
return HL();
case 0b11:
return SP();
default:
UNREACHABLE;
}
}
register16_t& RP(int rp) {
switch (rp) {
case 0b00:
@ -116,6 +135,21 @@ namespace EightBit {
}
}
register16_t RP2(int rp) const {
switch (rp) {
case 0b00:
return BC();
case 0b01:
return DE();
case 0b10:
return HL();
case 0b11:
return AF();
default:
UNREACHABLE;
}
}
register16_t& RP2(int rp) {
switch (rp) {
case 0b00:

View File

@ -13,7 +13,7 @@ EightBit::Disassembler::Disassembler() {
m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
}
std::string EightBit::Disassembler::state(Intel8080& cpu) {
std::string EightBit::Disassembler::state(const Intel8080& cpu) {
auto pc = cpu.PC();
auto sp = cpu.SP();
@ -160,13 +160,13 @@ std::string EightBit::Disassembler::alu2(int which) {
throw std::logic_error("Unhandled alu operation");
}
std::string EightBit::Disassembler::disassemble(Intel8080& cpu) {
std::string EightBit::Disassembler::disassemble(const Intel8080& cpu) {
std::ostringstream output;
disassemble(output, cpu, cpu.PC().word);
return output.str();
}
void EightBit::Disassembler::disassemble(std::ostringstream& output, Intel8080& cpu, uint16_t pc) {
void EightBit::Disassembler::disassemble(std::ostringstream& output, const Intel8080& cpu, uint16_t pc) {
auto& bus = cpu.BUS();
auto opcode = bus.peek(pc);

View File

@ -7,19 +7,37 @@ EightBit::Intel8080::Intel8080(Bus& bus, InputOutput& ports)
}
EightBit::register16_t& EightBit::Intel8080::AF() {
auto& f = af.low;
f = (f | Bit1) & ~(Bit5 | Bit3);
af.low = (af.low | Bit1) & ~(Bit5 | Bit3);
return af;
}
EightBit::register16_t EightBit::Intel8080::AF() const {
register16_t returned;
returned.low = (af.low | Bit1) & ~(Bit5 | Bit3);
returned.high = af.high;
return returned;
}
EightBit::register16_t EightBit::Intel8080::BC() const {
return bc;
}
EightBit::register16_t& EightBit::Intel8080::BC() {
return bc;
}
EightBit::register16_t EightBit::Intel8080::DE() const {
return de;
}
EightBit::register16_t& EightBit::Intel8080::DE() {
return de;
}
EightBit::register16_t EightBit::Intel8080::HL() const {
return hl;
}
EightBit::register16_t& EightBit::Intel8080::HL() {
return hl;
}
@ -240,7 +258,7 @@ void EightBit::Intel8080::xhtl(register16_t& operand) {
void EightBit::Intel8080::writePort(uint8_t port, uint8_t data) {
BUS().ADDRESS().low = port;
BUS().ADDRESS().high = data;
BUS().placeDATA(data);
BUS().DATA() = data;
writePort();
}
@ -256,7 +274,7 @@ void EightBit::Intel8080::readPort(uint8_t port, uint8_t& a) {
}
void EightBit::Intel8080::readPort() {
BUS().placeDATA(m_ports.read(BUS().ADDRESS().low));
BUS().DATA() = m_ports.read(BUS().ADDRESS().low);
}
int EightBit::Intel8080::step() {

View File

@ -33,9 +33,8 @@ void Board::initialise() {
CPU().PC() = m_configuration.getStartAddress();
}
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080&) {
auto pc = CPU().PC();
switch (pc.word) {
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080& cpu) {
switch (cpu.PC().word) {
case 0x0: // CP/M warm start
CPU().powerOff();
if (m_configuration.isProfileMode()) {
@ -50,11 +49,10 @@ void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080&) {
}
}
void Board::bdos() {
auto c = CPU().C();
switch (c) {
void Board::bdos() const {
switch (CPU().C()) {
case 0x2: {
auto character = CPU().E();
const auto character = CPU().E();
std::cout << character;
break;
}
@ -68,13 +66,13 @@ void Board::bdos() {
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpu) {
const auto pc = CPU().PC();
const auto pc = cpu.PC();
m_profiler.addAddress(pc.word);
m_profiler.addInstruction(peek(pc.word));
}
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080&) {
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080& cpu) {
std::cerr
<< EightBit::Disassembler::state(CPU())

View File

@ -15,6 +15,7 @@ public:
Board(const Configuration& configuration);
EightBit::Intel8080& CPU() { return m_cpu; }
const EightBit::Intel8080& CPU() const { return m_cpu; }
void initialise();
@ -24,6 +25,11 @@ protected:
return m_ram.reference(address);
}
virtual uint8_t reference(uint16_t address, bool& rom) const {
rom = false;
return m_ram.reference(address);
}
private:
const Configuration& m_configuration;
EightBit::Ram m_ram = 0x10000;
@ -34,8 +40,8 @@ private:
void Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080& cpu);
void Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080& cpuEvent);
void Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpuEvent);
void Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080& cpu);
void Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpu);
void bdos();
void bdos() const;
};

View File

@ -42,6 +42,11 @@ namespace Fuse {
return m_ram.reference(address);
}
virtual uint8_t reference(uint16_t address, bool& rom) const {
rom = false;
return m_ram.reference(address);
}
public:
TestRunner(const Test& test, const ExpectedTestResult& expected);

View File

@ -36,9 +36,13 @@ namespace EightBit {
Bus();
LR35902& CPU() { return m_cpu; }
const LR35902& CPU() const { return m_cpu; }
Ram& VRAM() { return m_videoRam; }
const Ram& VRAM() const { return m_videoRam; }
Ram& OAMRAM() { return m_oamRam; }
const Ram& OAMRAM() const { return m_oamRam; }
IoRegisters& IO() { return m_ioPorts; }
const IoRegisters& IO() const { return m_ioPorts; }
void reset();
@ -56,6 +60,7 @@ namespace EightBit {
protected:
virtual uint8_t& reference(uint16_t address, bool& rom);
virtual uint8_t reference(uint16_t address, bool& rom) const;
private:
LR35902 m_cpu;

View File

@ -35,8 +35,18 @@ namespace EightBit {
return af;
}
register16_t AF() const final {
register16_t returned;
returned.low = higherNibble(af.low);
returned.high = af.high;
return returned;
}
virtual register16_t BC() const final { return bc; }
virtual register16_t& BC() final { return bc; }
virtual register16_t DE() const final { return de; }
virtual register16_t& DE() final { return de; }
virtual register16_t HL() const final { return hl; }
virtual register16_t& HL() final { return hl; }
int singleStep();

View File

@ -148,7 +148,7 @@ void EightBit::GameBoy::Bus::validateCartridgeType() {
}
}
uint8_t& EightBit::GameBoy::Bus::reference(uint16_t address, bool& rom) {
uint8_t EightBit::GameBoy::Bus::reference(uint16_t address, bool& rom) const {
rom = true;
if ((address < 0x100) && IO().bootRomEnabled())
@ -162,7 +162,7 @@ uint8_t& EightBit::GameBoy::Bus::reference(uint16_t address, bool& rom) {
if (address < 0xa000)
return VRAM().reference(address - 0x8000);
if (address < 0xc000)
return m_ramBanks.size() == 0 ? rom = true, placeDATA(0xff) : m_ramBanks[m_ramBank].reference(address - 0xa000);
return m_ramBanks.size() == 0 ? rom = true, 0xff : m_ramBanks[m_ramBank].reference(address - 0xa000);
if (address < 0xe000)
return m_lowInternalRam.reference(address - 0xc000);
if (address < 0xfe00)
@ -170,7 +170,35 @@ uint8_t& EightBit::GameBoy::Bus::reference(uint16_t address, bool& rom) {
if (address < 0xfea0)
return OAMRAM().reference(address - 0xfe00);
if (address < IoRegisters::BASE)
return rom = true, placeDATA(0xff);
return rom = true, 0xff;
if (address < 0xff80)
return IO().reference(address - IoRegisters::BASE);
return m_highInternalRam.reference(address - 0xff80);
}
uint8_t& EightBit::GameBoy::Bus::reference(uint16_t address, bool& rom) {
rom = true;
if ((address < 0x100) && IO().bootRomEnabled())
return DATA() = m_bootRom.reference(address);
if ((address < 0x4000) && gameRomEnabled())
return DATA() = m_gameRomBanks[0].reference(address);
if ((address < 0x8000) && gameRomEnabled())
return DATA() = m_gameRomBanks[m_romBank].reference(address - 0x4000);
rom = false;
if (address < 0xa000)
return VRAM().reference(address - 0x8000);
if (address < 0xc000)
return m_ramBanks.size() == 0 ? rom = true, DATA() = 0xff : m_ramBanks[m_ramBank].reference(address - 0xa000);
if (address < 0xe000)
return m_lowInternalRam.reference(address - 0xc000);
if (address < 0xfe00)
return m_lowInternalRam.reference(address - 0xe000); // Low internal RAM mirror
if (address < 0xfea0)
return OAMRAM().reference(address - 0xfe00);
if (address < IoRegisters::BASE)
return rom = true, DATA() = 0xff;
if (address < 0xff80)
return IO().reference(address - IoRegisters::BASE);
return m_highInternalRam.reference(address - 0xff80);

View File

@ -290,7 +290,7 @@ int EightBit::GameBoy::LR35902::singleStep() {
m_bus.IO().poke(IoRegisters::IF, 0);
lower(INT());
const int index = EightBit::findFirstSet(masked);
BUS().placeDATA(0x38 + (index << 3));
BUS().DATA() = 0x38 + (index << 3);
} else {
if (halted())
proceed();

View File

@ -33,12 +33,18 @@ namespace EightBit {
virtual int step() final;
virtual void powerOn() override;
uint8_t X() const { return x; }
uint8_t& X() { return x; }
uint8_t Y() const { return y; }
uint8_t& Y() { return y; }
uint8_t A() const { return a; }
uint8_t& A() { return a; }
uint8_t S() const { return s; }
uint8_t& S() { return s; }
uint8_t P() const { return p; }
uint8_t& P() { return p; }
PinLevel SO() const { return m_soLine; } // In
PinLevel& SO() { return m_soLine; } // In
protected:
@ -330,6 +336,6 @@ namespace EightBit {
PinLevel m_soLine = Low;
register16_t m_intermediate = { { 0, 0 } };;
register16_t m_intermediate = { { 0, 0 } };
};
}

View File

@ -9,14 +9,9 @@
Board::Board(const Configuration& configuration)
: m_configuration(configuration),
m_ram(0x10000),
m_cpu(EightBit::MOS6502(*this)),
m_symbols(""),
m_disassembler(m_cpu, m_symbols),
m_profiler(m_cpu, m_disassembler, m_symbols),
m_oldPC(0xffff),
m_stopped(false) {
}
m_profiler(m_cpu, m_disassembler, m_symbols) {}
void Board::initialise() {
@ -76,7 +71,7 @@ void Board::Cpu_ExecutingInstruction_Profile(const EightBit::MOS6502& cpu) {
void Board::Cpu_ExecutedInstruction_StopLoop(const EightBit::MOS6502& cpu) {
auto pc = CPU().PC().word;
auto pc = cpu.PC().word;
if (m_oldPC == pc) {
CPU().powerOff();
auto test = peek(0x0200);
@ -88,7 +83,7 @@ void Board::Cpu_ExecutedInstruction_StopLoop(const EightBit::MOS6502& cpu) {
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::MOS6502& cpu) {
auto address = CPU().PC().word;
auto address = cpu.PC().word;
auto cell = peek(address);
std::cout << std::hex;

View File

@ -25,18 +25,23 @@ protected:
return m_ram.reference(address);
}
virtual uint8_t reference(uint16_t address, bool& rom) const {
rom = false;
return m_ram.reference(address);
}
private:
const Configuration& m_configuration;
EightBit::Ram m_ram;
EightBit::Ram m_ram = 0x10000;
EightBit::MOS6502 m_cpu;
EightBit::Symbols m_symbols;
EightBit::Symbols m_symbols = "";
EightBit::Disassembly m_disassembler;
EightBit::Profiler m_profiler;
uint16_t m_oldPC;
bool m_stopped;
uint64_t m_pollCounter;
uint64_t m_pollInterval;
uint16_t m_oldPC = 0xffff;
bool m_stopped = false;
uint64_t m_pollCounter = 0UL;
uint64_t m_pollInterval = 0UL;
void pollKeyboard();

View File

@ -41,6 +41,11 @@ namespace Fuse {
return m_ram.reference(address);
}
virtual uint8_t reference(uint16_t address, bool& rom) const {
rom = false;
return m_ram.reference(address);
}
public:
TestRunner(const Test& test, const ExpectedTestResult& expected);

View File

@ -11,8 +11,8 @@ namespace EightBit {
public:
Disassembler();
static std::string state(Z80& cpu);
std::string disassemble(Z80& cpu);
static std::string state(const Z80& cpu);
std::string disassemble(const Z80& cpu);
static std::string flag(uint8_t value, int flag, const std::string& represents);
static std::string flags(uint8_t value);
@ -30,29 +30,29 @@ namespace EightBit {
bool m_prefixED;
bool m_prefixFD;
void disassemble(std::ostringstream& output, Z80& cpu, uint16_t pc);
void disassemble(std::ostringstream& output, const Z80& cpu, uint16_t pc);
void disassembleCB(
std::ostringstream& output,
Z80& cpu,
const Z80& cpu,
uint16_t pc,
std::string& specification,
int& dumpCount,
int x, int y, int z,
int p, int q);
int p, int q) const;
void disassembleED(
std::ostringstream& output,
Z80& cpu,
const Z80& cpu,
uint16_t pc,
std::string& specification,
int& dumpCount,
int x, int y, int z,
int p, int q);
int p, int q) const;
void disassembleOther(
std::ostringstream& output,
Z80& cpu,
const Z80& cpu,
uint16_t pc,
std::string& specification,
int& dumpCount,

View File

@ -51,28 +51,44 @@ namespace EightBit {
Signal<Z80> ExecutingInstruction;
PinLevel& M1() { return m_m1Line; } // Out
PinLevel M1() const { return m_m1Line; }
virtual int execute(uint8_t opcode) final;
virtual int step() final;
virtual register16_t& AF() final;
virtual register16_t AF() const final;
virtual register16_t& BC() final;
virtual register16_t BC() const final;
virtual register16_t& DE() final;
virtual register16_t DE() const final;
virtual register16_t& HL() final;
virtual register16_t HL() const final;
register16_t& IX() { return m_ix; }
register16_t IX() const { return m_ix; }
uint8_t& IXH() { return IX().high; }
uint8_t IXH() const { return IX().high; }
uint8_t& IXL() { return IX().low; }
uint8_t IXL() const { return IX().low; }
register16_t& IY() { return m_iy; }
register16_t IY() const { return m_iy; }
uint8_t& IYH() { return IY().high; }
uint8_t IYH() const { return IY().high; }
uint8_t& IYL() { return IY().low; }
uint8_t IYL() const { return IY().low; }
refresh_t& REFRESH() { return m_refresh; }
refresh_t REFRESH() const { return m_refresh; }
uint8_t& IV() { return iv; }
uint8_t IV() const { return iv; }
int& IM() { return m_interruptMode; }
int IM() const { return m_interruptMode; }
bool& IFF1() { return m_iff1; }
bool IFF1() const { return m_iff1; }
bool& IFF2() { return m_iff2; }
bool IFF2() const { return m_iff2; }
void exx() {
m_registerSet ^= 1;
@ -258,6 +274,23 @@ namespace EightBit {
}
}
register16_t RP(const int rp) const {
ASSUME(rp >= 0);
ASSUME(rp <= 3);
switch (rp) {
case 0:
return BC();
case 1:
return DE();
case 2:
return HL2();
case 3:
return SP();
default:
UNREACHABLE;
}
}
register16_t& HL2() {
if (LIKELY(!m_displaced))
return HL();
@ -267,6 +300,15 @@ namespace EightBit {
return IY();
}
register16_t HL2() const {
if (LIKELY(!m_displaced))
return HL();
if (m_prefixDD)
return IX();
// Must be FD prefix
return IY();
}
register16_t& RP2(const int rp) {
ASSUME(rp >= 0);
ASSUME(rp <= 3);
@ -284,6 +326,23 @@ namespace EightBit {
}
}
register16_t RP2(const int rp) const {
ASSUME(rp >= 0);
ASSUME(rp <= 3);
switch (rp) {
case 0:
return BC();
case 1:
return DE();
case 2:
return HL2();
case 3:
return AF();
default:
UNREACHABLE;
}
}
static void adjustHalfCarryAdd(uint8_t& f, const uint8_t before, const uint8_t value, const int calculation) {
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
}

View File

@ -15,7 +15,7 @@ EightBit::Disassembler::Disassembler() {
m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
}
std::string EightBit::Disassembler::state(Z80& cpu) {
std::string EightBit::Disassembler::state(const Z80& cpu) {
auto pc = cpu.PC();
auto sp = cpu.SP();
@ -171,14 +171,14 @@ std::string EightBit::Disassembler::alu(int which) {
throw std::logic_error("Unhandled alu operation");
}
std::string EightBit::Disassembler::disassemble(Z80& cpu) {
std::string EightBit::Disassembler::disassemble(const Z80& cpu) {
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
std::ostringstream output;
disassemble(output, cpu, cpu.PC().word);
return output.str();
}
void EightBit::Disassembler::disassemble(std::ostringstream& output, Z80& cpu, uint16_t pc) {
void EightBit::Disassembler::disassemble(std::ostringstream& output, const Z80& cpu, uint16_t pc) {
auto& bus = cpu.BUS();
auto opcode = bus.peek(pc);
@ -239,12 +239,12 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, Z80& cpu, u
void EightBit::Disassembler::disassembleCB(
std::ostringstream& output,
Z80& cpu,
const Z80& cpu,
uint16_t pc,
std::string& specification,
int& dumpCount,
int x, int y, int z,
int p, int q) {
int p, int q) const {
switch (x) {
case 0: // rot[y] r[z]
@ -289,12 +289,12 @@ void EightBit::Disassembler::disassembleCB(
void EightBit::Disassembler::disassembleED(
std::ostringstream& output,
Z80& cpu,
const Z80& cpu,
uint16_t pc,
std::string& specification,
int& dumpCount,
int x, int y, int z,
int p, int q) {
int p, int q) const {
switch (x) {
case 0:
case 3:
@ -423,7 +423,7 @@ void EightBit::Disassembler::disassembleED(
void EightBit::Disassembler::disassembleOther(
std::ostringstream& output,
Z80& cpu,
const Z80& cpu,
uint16_t pc,
std::string& specification,
int& dumpCount,

View File

@ -8,18 +8,34 @@ EightBit::Z80::Z80(Bus& bus, InputOutput& ports)
m_ports(ports) {
}
EightBit::register16_t EightBit::Z80::AF() const {
return m_accumulatorFlags[m_accumulatorFlagsSet];
}
EightBit::register16_t& EightBit::Z80::AF() {
return m_accumulatorFlags[m_accumulatorFlagsSet];
}
EightBit::register16_t EightBit::Z80::BC() const {
return m_registers[m_registerSet][BC_IDX];
}
EightBit::register16_t& EightBit::Z80::BC() {
return m_registers[m_registerSet][BC_IDX];
}
EightBit::register16_t EightBit::Z80::DE() const {
return m_registers[m_registerSet][DE_IDX];
}
EightBit::register16_t& EightBit::Z80::DE() {
return m_registers[m_registerSet][DE_IDX];
}
EightBit::register16_t EightBit::Z80::HL() const {
return m_registers[m_registerSet][HL_IDX];
}
EightBit::register16_t& EightBit::Z80::HL() {
return m_registers[m_registerSet][HL_IDX];
}
@ -621,7 +637,7 @@ void EightBit::Z80::writePort(const uint8_t port, const uint8_t data) {
BUS().ADDRESS().low = port;
BUS().ADDRESS().high = data;
MEMPTR() = BUS().ADDRESS();
BUS().placeDATA(data);
BUS().DATA() = data;
writePort();
++MEMPTR().low;
}
@ -640,7 +656,7 @@ void EightBit::Z80::readPort(const uint8_t port, uint8_t& a) {
}
void EightBit::Z80::readPort() {
BUS().placeDATA(m_ports.read(BUS().ADDRESS().low));
BUS().DATA() = m_ports.read(BUS().ADDRESS().low);
}
int EightBit::Z80::step() {
@ -844,22 +860,22 @@ void EightBit::Z80::executeED(uint8_t& a, uint8_t& f, const int x, const int y,
case 1:
switch (z) {
case 0: // Input from port with 16-bit address
MEMPTR() = BUS().ADDRESS() = BC();
++MEMPTR().word;
MEMPTR() = BUS().ADDRESS() = BC();
++MEMPTR().word;
readPort();
if (LIKELY(y != 6)) // IN r[y],(C)
if (LIKELY(y != 6)) // IN r[y],(C)
R(y, a, BUS().DATA());
adjustSZPXY<Z80>(f, BUS().DATA());
clearFlag(f, NF | HC);
addCycles(12);
clearFlag(f, NF | HC);
addCycles(12);
break;
case 1: // Output to port with 16-bit address
MEMPTR() = BUS().ADDRESS() = BC();
++MEMPTR().word;
if (UNLIKELY(y == 6)) // OUT (C),0
BUS().placeDATA(0);
BUS().DATA() = 0;
else // OUT (C),r[y]
BUS().placeDATA(R(y, a));
BUS().DATA() = R(y, a);
writePort();
addCycles(12);
break;
@ -1140,7 +1156,8 @@ void EightBit::Z80::executeOther(uint8_t& a, uint8_t& f, const int x, const int
case 0: // LD (BC),A
MEMPTR() = BUS().ADDRESS() = BC();
++MEMPTR().word;
BUS().write(a);
BUS().DATA() = a;
BUS().write();
MEMPTR().high = a;
addCycles(7);
break;

View File

@ -34,13 +34,12 @@ void Board::initialise() {
CPU().PC() = m_configuration.getStartAddress();
}
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Z80&) {
if (UNLIKELY(EightBit::Processor::lowered(m_cpu.HALT())))
m_cpu.powerOff();
auto pc = m_cpu.PC();
switch (pc.word) {
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Z80& cpu) {
if (UNLIKELY(EightBit::Processor::lowered(cpu.HALT())))
CPU().powerOff();
switch (cpu.PC().word) {
case 0x0: // CP/M warm start
m_cpu.powerOff();
CPU().powerOff();
if (m_configuration.isProfileMode()) {
m_profiler.dump();
}
@ -53,16 +52,13 @@ void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Z80&) {
}
}
void Board::bdos() {
auto c = m_cpu.C();
switch (c) {
case 0x2: {
auto character = m_cpu.E();
std::cout << character;
void Board::bdos() const {
switch (CPU().C()) {
case 0x2:
std::cout << CPU().E();
break;
}
case 0x9:
for (uint16_t i = m_cpu.DE().word; peek(i) != '$'; ++i) {
for (uint16_t i = CPU().DE().word; peek(i) != '$'; ++i) {
std::cout << peek(i);
}
break;
@ -71,7 +67,7 @@ void Board::bdos() {
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpu) {
const auto pc = m_cpu.PC();
const auto pc = cpu.PC();
m_profiler.addAddress(pc.word);
m_profiler.addInstruction(peek(pc.word));
@ -80,8 +76,8 @@ void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpu) {
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Z80& cpu) {
std::cerr
<< EightBit::Disassembler::state(m_cpu)
<< EightBit::Disassembler::state(cpu)
<< "\t"
<< m_disassembler.disassemble(m_cpu)
<< m_disassembler.disassemble(cpu)
<< '\n';
}

View File

@ -17,6 +17,7 @@ public:
Board(const Configuration& configuration);
EightBit::Z80& CPU() { return m_cpu; }
const EightBit::Z80& CPU() const { return m_cpu; }
void initialise();
@ -26,6 +27,11 @@ protected:
return m_ram.reference(address);
}
virtual uint8_t reference(uint16_t address, bool& rom) const {
rom = false;
return m_ram.reference(address);
}
private:
const Configuration& m_configuration;
EightBit::Ram m_ram = 0x10000;
@ -36,8 +42,8 @@ private:
void Cpu_ExecutingInstruction_Cpm(const EightBit::Z80& cpu);
void Cpu_ExecutingInstruction_Debug(const EightBit::Z80& cpuEvent);
void Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpuEvent);
void Cpu_ExecutingInstruction_Debug(const EightBit::Z80& cpu);
void Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpu);
void bdos();
void bdos() const;
};

View File

@ -16,32 +16,34 @@ namespace EightBit {
Signal<uint16_t> ReadingByte;
Signal<uint16_t> ReadByte;
register16_t& ADDRESS();
uint8_t& DATA();
register16_t& ADDRESS() { return m_address; }
register16_t ADDRESS() const { return m_address; }
uint8_t& DATA() { return m_data; }
uint8_t DATA() const { return m_data; }
uint8_t& placeDATA(uint8_t value);
uint8_t& referenceDATA(uint8_t& value);
uint8_t peek(uint16_t address);
uint8_t peek(uint16_t address) const;
void poke(uint16_t address, uint8_t value);
uint16_t peekWord(uint16_t address);
uint16_t peekWord(uint16_t address) const;
uint8_t read();
uint8_t read(uint16_t offset);
uint8_t read(register16_t address);
void write();
void write(uint8_t value);
void write(uint16_t offset, uint8_t value);
void write(register16_t address, uint8_t value);
protected:
virtual uint8_t& reference(uint16_t address, bool& rom) = 0;
virtual uint8_t reference(uint16_t address, bool& rom) const = 0;
uint8_t& reference();
uint8_t reference() const;
private:
uint8_t* m_data = nullptr;
uint8_t m_data = 0xff;
register16_t m_address{ { 0xff, 0xff } };
uint8_t m_temporary = 0xff; // Used to simulate ROM
};
}

View File

@ -37,24 +37,38 @@ namespace EightBit {
}
register16_t& MEMPTR() { return m_memptr; }
register16_t MEMPTR() const { return m_memptr; }
register16_t& SP() { return m_sp; }
register16_t SP() const { return m_sp; }
virtual register16_t& AF() = 0;
virtual register16_t AF() const = 0;
uint8_t& A() { return AF().high; }
uint8_t A() const { return AF().high; }
uint8_t& F() { return AF().low; }
uint8_t F() const { return AF().low; }
virtual register16_t& BC() = 0;
virtual register16_t BC() const = 0;
uint8_t& B() { return BC().high; }
uint8_t B() const { return BC().high; }
uint8_t& C() { return BC().low; }
uint8_t C() const { return BC().low; }
virtual register16_t& DE() = 0;
virtual register16_t DE() const = 0;
uint8_t& D() { return DE().high; }
uint8_t D() const { return DE().high; }
uint8_t& E() { return DE().low; }
uint8_t E() const { return DE().low; }
virtual register16_t& HL() = 0;
virtual register16_t HL() const = 0;
uint8_t& H() { return HL().high; }
uint8_t H() const { return HL().high; }
uint8_t& L() { return HL().low; }
uint8_t L() const { return HL().low; }
protected:
IntelProcessor(Bus& bus);

View File

@ -34,15 +34,16 @@ namespace EightBit {
return limit;
}
protected:
std::vector<uint8_t>& BYTES() { return m_bytes; }
uint8_t read(const uint16_t address) const {
return m_bytes[address];
uint8_t peek(const uint16_t address) const {
return BYTES()[address];
}
void write(const uint16_t address, const uint8_t value) {
m_bytes[address] = value;
protected:
std::vector<uint8_t>& BYTES() { return m_bytes; }
const std::vector<uint8_t>& BYTES() const { return m_bytes; }
void poke(const uint16_t address, const uint8_t value) {
BYTES()[address] = value;
}
private:

View File

@ -68,16 +68,27 @@ namespace EightBit {
static int demoteNibble(const int value) { return highNibble(value); }
Bus& BUS() { return m_bus; }
const Bus& BUS() const { return m_bus; }
register16_t& PC() { return m_pc; }
register16_t PC() const { return m_pc; }
PinLevel& RESET() { return m_resetLine; } // In
PinLevel& HALT() { return m_haltLine; } // Out
PinLevel& INT() { return m_intLine; } // In
PinLevel& NMI() { return m_nmiLine; } // In
PinLevel& POWER() { return m_powerLine; } // In
PinLevel& RESET() { return m_resetLine; }
PinLevel RESET() const { return m_resetLine; } // In
bool powered() { return raised(POWER()); }
PinLevel& HALT() { return m_haltLine; }
PinLevel HALT() const { return m_haltLine; } // Out
PinLevel& INT() { return m_intLine; }
PinLevel INT() const { return m_intLine; } // In
PinLevel& NMI() { return m_nmiLine; }
PinLevel NMI() const { return m_nmiLine; } // In
PinLevel& POWER() { return m_powerLine; }
PinLevel POWER() const { return m_powerLine; } // In
bool powered() const { return raised(POWER()); }
virtual void powerOn() { raise(POWER()); raise(HALT()); reset(); }
void powerOff() { lower(POWER()); }
@ -104,7 +115,7 @@ namespace EightBit {
virtual void reset();
bool halted() { return lowered(HALT()); }
bool halted() const { return lowered(HALT()); }
void halt() { --PC().word; lower(HALT()); }
void proceed() { ++PC().word; raise(HALT()); }

View File

@ -10,16 +10,16 @@ namespace EightBit {
: Memory(size) {
}
uint8_t peek(const uint16_t address) const {
return read(address);
}
void poke(const uint16_t address, const uint8_t value) {
write(address, value);
}
uint8_t& reference(const uint16_t address) {
return BYTES()[address];
}
uint8_t reference(uint16_t address) const {
return peek(address);
}
void poke(uint16_t address, uint8_t value) {
Memory::poke(address, value);
}
};
}

View File

@ -10,12 +10,8 @@ namespace EightBit {
: Memory(size) {
}
uint8_t peek(const uint16_t address) const {
return read(address);
}
uint8_t& reference(const uint16_t address) {
return BYTES()[address];
uint8_t reference(uint16_t address) const {
return peek(address);
}
};
}

View File

@ -3,26 +3,7 @@
#include "EightBitCompilerDefinitions.h"
EightBit::register16_t& EightBit::Bus::ADDRESS() {
return m_address;
}
uint8_t& EightBit::Bus::DATA() {
return *m_data;
}
uint8_t& EightBit::Bus::placeDATA(const uint8_t value) {
m_temporary = value;
m_data = &m_temporary;
return DATA();
}
uint8_t& EightBit::Bus::referenceDATA(uint8_t& value) {
m_data = &value;
return DATA();
}
uint8_t EightBit::Bus::peek(const uint16_t address) {
uint8_t EightBit::Bus::peek(const uint16_t address) const {
bool rom;
return reference(address, rom);
}
@ -32,7 +13,7 @@ void EightBit::Bus::poke(const uint16_t address, const uint8_t value) {
reference(address, rom) = value;
}
uint16_t EightBit::Bus::peekWord(const uint16_t address) {
uint16_t EightBit::Bus::peekWord(const uint16_t address) const {
register16_t returned;
returned.low = peek(address);
returned.high = peek(address + 1);
@ -41,9 +22,9 @@ uint16_t EightBit::Bus::peekWord(const uint16_t address) {
uint8_t EightBit::Bus::read() {
ReadingByte.fire(ADDRESS().word);
const auto returned = reference();
DATA() = reference();
ReadByte.fire(ADDRESS().word);
return returned;
return DATA();
}
uint8_t EightBit::Bus::read(const uint16_t offset) {
@ -56,12 +37,17 @@ uint8_t EightBit::Bus::read(const register16_t address) {
return read();
}
void EightBit::Bus::write(const uint8_t value) {
void EightBit::Bus::write() {
WritingByte.fire(ADDRESS().word);
reference() = value;
reference() = DATA();
WrittenByte.fire(ADDRESS().word);
}
void EightBit::Bus::write(const uint8_t value) {
DATA() = value;
write();
}
void EightBit::Bus::write(const uint16_t offset, const uint8_t value) {
ADDRESS().word = offset;
write(value);
@ -72,8 +58,12 @@ void EightBit::Bus::write(const register16_t address, const uint8_t value) {
write(value);
}
uint8_t EightBit::Bus::reference() const {
bool rom;
return reference(ADDRESS().word, rom);
}
uint8_t& EightBit::Bus::reference() {
bool rom;
auto& value = reference(ADDRESS().word, rom);
return rom ? placeDATA(value) : referenceDATA(value);
return reference(ADDRESS().word, rom);
}