Reflect that the I/O for Intel style processors isn't part of the CPU, but attached to the Bus and access controlled by the CPU.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon
2020-02-09 11:51:58 +00:00
parent dc37d61797
commit c8bdabf34f
24 changed files with 410 additions and 279 deletions

Binary file not shown.

View File

@@ -6,7 +6,6 @@
#include <stdexcept> #include <stdexcept>
#include <Bus.h> #include <Bus.h>
#include <InputOutput.h>
#include <IntelProcessor.h> #include <IntelProcessor.h>
#include <EventArgs.h> #include <EventArgs.h>
#include <Signal.h> #include <Signal.h>
@@ -23,7 +22,7 @@ namespace EightBit {
CF = Bit0, CF = Bit0,
}; };
Intel8080(Bus& bus, InputOutput& ports); Intel8080(Bus& bus);
Signal<Intel8080> ExecutingInstruction; Signal<Intel8080> ExecutingInstruction;
Signal<Intel8080> ExecutedInstruction; Signal<Intel8080> ExecutedInstruction;
@@ -36,14 +35,30 @@ namespace EightBit {
virtual register16_t& DE() final; virtual register16_t& DE() final;
virtual register16_t& HL() final; virtual register16_t& HL() final;
bool requestingIO() { return m_requestIO; }
bool requestingMemory() { return m_requestMemory; }
bool requestingRead() { return raised(DBIN()); }
bool requestingWrite() { return lowered(WR()); }
DECLARE_PIN_OUTPUT(DBIN) // Active high
DECLARE_PIN_OUTPUT(WR) // Active low
protected: protected:
virtual void handleRESET() final; void handleRESET() final;
virtual void handleINT() final; void handleINT() final;
void memoryWrite() final;
uint8_t memoryRead() final;
void busWrite() final;
uint8_t busRead() final;
private: private:
bool m_interruptEnable = false; bool m_requestIO = false;
bool m_requestMemory = false;
InputOutput& m_ports; bool m_interruptEnable = false;
register16_t af; register16_t af;
register16_t bc = Mask16; register16_t bc = Mask16;
@@ -65,7 +80,7 @@ namespace EightBit {
case 0b101: case 0b101:
return L(); return L();
case 0b110: case 0b110:
return busRead(HL()); return IntelProcessor::memoryRead(HL());
case 0b111: case 0b111:
return A(); return A();
default: default:
@@ -94,7 +109,7 @@ namespace EightBit {
L() = value; L() = value;
break; break;
case 0b110: case 0b110:
busWrite(HL(), value); IntelProcessor::memoryWrite(HL(), value);
break; break;
case 0b111: case 0b111:
A() = value; A() = value;
@@ -179,10 +194,10 @@ namespace EightBit {
void xhtl(register16_t& exchange); void xhtl(register16_t& exchange);
void writePort(uint8_t port); void portWrite(uint8_t port);
void writePort(); void portWrite();
uint8_t readPort(uint8_t port); uint8_t portRead(uint8_t port);
uint8_t readPort(); uint8_t portRead();
}; };
} }

View File

@@ -1,11 +1,13 @@
#include "stdafx.h" #include "stdafx.h"
#include "Intel8080.h" #include "Intel8080.h"
EightBit::Intel8080::Intel8080(Bus& bus, InputOutput& ports) EightBit::Intel8080::Intel8080(Bus& bus)
: IntelProcessor(bus), : IntelProcessor(bus){
m_ports(ports) {
} }
DEFINE_PIN_LEVEL_CHANGERS(DBIN, Intel8080);
DEFINE_PIN_LEVEL_CHANGERS(WR, Intel8080);
EightBit::register16_t& EightBit::Intel8080::AF() { EightBit::register16_t& EightBit::Intel8080::AF() {
af.low = (af.low | Bit1) & ~(Bit5 | Bit3); af.low = (af.low | Bit1) & ~(Bit5 | Bit3);
return af; return af;
@@ -23,6 +25,31 @@ EightBit::register16_t& EightBit::Intel8080::HL() {
return hl; return hl;
} }
void EightBit::Intel8080::memoryWrite() {
m_requestMemory = true;
IntelProcessor::memoryWrite();
m_requestMemory = false;
}
uint8_t EightBit::Intel8080::memoryRead() {
m_requestMemory = true;
return IntelProcessor::memoryRead();
m_requestMemory = false;
}
void EightBit::Intel8080::busWrite() {
lowerWR();
IntelProcessor::busWrite();
raiseWR();
}
uint8_t EightBit::Intel8080::busRead() {
raiseDBIN();
const auto returned = IntelProcessor::busRead();
lowerDBIN();
return returned;
}
void EightBit::Intel8080::handleRESET() { void EightBit::Intel8080::handleRESET() {
IntelProcessor::handleRESET(); IntelProcessor::handleRESET();
di(); di();
@@ -236,33 +263,37 @@ void EightBit::Intel8080::cmc() {
} }
void EightBit::Intel8080::xhtl(register16_t& exchange) { void EightBit::Intel8080::xhtl(register16_t& exchange) {
MEMPTR().low = busRead(SP()); MEMPTR().low = IntelProcessor::memoryRead(SP());
++BUS().ADDRESS(); ++BUS().ADDRESS();
MEMPTR().high = busRead(); MEMPTR().high = memoryRead();
busWrite(exchange.high); IntelProcessor::memoryWrite(exchange.high);
exchange.high = MEMPTR().high; exchange.high = MEMPTR().high;
--BUS().ADDRESS(); --BUS().ADDRESS();
busWrite(exchange.low); IntelProcessor::memoryWrite(exchange.low);
exchange.low = MEMPTR().low; exchange.low = MEMPTR().low;
} }
void EightBit::Intel8080::writePort(const uint8_t port) { void EightBit::Intel8080::portWrite(const uint8_t port) {
BUS().ADDRESS() = register16_t(port, A()); BUS().ADDRESS() = { port, port };
BUS().DATA() = A(); portWrite();
writePort();
} }
void EightBit::Intel8080::writePort() { void EightBit::Intel8080::portWrite() {
m_ports.write(BUS().ADDRESS().low, BUS().DATA()); m_requestIO = true;
busWrite();
m_requestIO = false;
} }
uint8_t EightBit::Intel8080::readPort(const uint8_t port) { uint8_t EightBit::Intel8080::portRead(const uint8_t port) {
BUS().ADDRESS() = register16_t(port, A()); BUS().ADDRESS() = { port, port };
return readPort(); return portRead();
} }
uint8_t EightBit::Intel8080::readPort() { uint8_t EightBit::Intel8080::portRead() {
return BUS().DATA() = m_ports.read(BUS().ADDRESS().low); m_requestIO = true;
const auto returned = busRead();
m_requestIO = false;
return returned;
} }
int EightBit::Intel8080::step() { int EightBit::Intel8080::step() {
@@ -330,11 +361,11 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
case 0: case 0:
switch (p) { switch (p) {
case 0: // LD (BC),A case 0: // LD (BC),A
busWrite(BC(), A()); IntelProcessor::memoryWrite(BC(), A());
tick(7); tick(7);
break; break;
case 1: // LD (DE),A case 1: // LD (DE),A
busWrite(DE(), A()); IntelProcessor::memoryWrite(DE(), A());
tick(7); tick(7);
break; break;
case 2: // LD (nn),HL case 2: // LD (nn),HL
@@ -344,7 +375,7 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
break; break;
case 3: // LD (nn),A case 3: // LD (nn),A
BUS().ADDRESS() = fetchWord(); BUS().ADDRESS() = fetchWord();
busWrite(A()); IntelProcessor::memoryWrite(A());
tick(13); tick(13);
break; break;
default: default:
@@ -354,11 +385,11 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
case 1: case 1:
switch (p) { switch (p) {
case 0: // LD A,(BC) case 0: // LD A,(BC)
A() = busRead(BC()); A() = IntelProcessor::memoryRead(BC());
tick(7); tick(7);
break; break;
case 1: // LD A,(DE) case 1: // LD A,(DE)
A() = busRead(DE()); A() = IntelProcessor::memoryRead(DE());
tick(7); tick(7);
break; break;
case 2: // LD HL,(nn) case 2: // LD HL,(nn)
@@ -534,11 +565,11 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
tick(10); tick(10);
break; break;
case 2: // OUT (n),A case 2: // OUT (n),A
writePort(fetchByte()); portWrite(fetchByte());
tick(11); tick(11);
break; break;
case 3: // IN A,(n) case 3: // IN A,(n)
A() = readPort(fetchByte()); A() = portRead(fetchByte());
tick(11); tick(11);
break; break;
case 4: // EX (SP),HL case 4: // EX (SP),HL

View File

@@ -6,7 +6,7 @@
Board::Board(const Configuration& configuration) Board::Board(const Configuration& configuration)
: m_configuration(configuration), : m_configuration(configuration),
m_cpu(EightBit::Intel8080(*this, m_ports)), m_cpu(EightBit::Intel8080(*this)),
m_disassembler(*this) { m_disassembler(*this) {
} }

View File

@@ -74,7 +74,7 @@ namespace EightBit {
case 5: case 5:
return L(); return L();
case 6: case 6:
return busRead(HL()); return IntelProcessor::memoryRead(HL());
case 7: case 7:
return A(); return A();
default: default:
@@ -105,7 +105,7 @@ namespace EightBit {
L() = value; L() = value;
break; break;
case 6: case 6:
busWrite(HL(), value); IntelProcessor::memoryWrite(HL(), value);
break; break;
case 7: case 7:
A() = value; A() = value;

View File

@@ -473,19 +473,19 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
case 0: case 0:
switch (p) { switch (p) {
case 0: // LD (BC),A case 0: // LD (BC),A
busWrite(BC(), A()); IntelProcessor::memoryWrite(BC(), A());
tick(2); tick(2);
break; break;
case 1: // LD (DE),A case 1: // LD (DE),A
busWrite(DE(), A()); IntelProcessor::memoryWrite(DE(), A());
tick(2); tick(2);
break; break;
case 2: // GB: LDI (HL),A case 2: // GB: LDI (HL),A
busWrite(HL()++, A()); IntelProcessor::memoryWrite(HL()++, A());
tick(2); tick(2);
break; break;
case 3: // GB: LDD (HL),A case 3: // GB: LDD (HL),A
busWrite(HL()--, A()); IntelProcessor::memoryWrite(HL()--, A());
tick(2); tick(2);
break; break;
default: default:
@@ -495,19 +495,19 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
case 1: case 1:
switch (p) { switch (p) {
case 0: // LD A,(BC) case 0: // LD A,(BC)
A() = busRead(BC()); A() = IntelProcessor::memoryRead(BC());
tick(2); tick(2);
break; break;
case 1: // LD A,(DE) case 1: // LD A,(DE)
A() = busRead(DE()); A() = IntelProcessor::memoryRead(DE());
tick(2); tick(2);
break; break;
case 2: // GB: LDI A,(HL) case 2: // GB: LDI A,(HL)
A() = busRead(HL()++); A() = IntelProcessor::memoryRead(HL()++);
tick(2); tick(2);
break; break;
case 3: // GB: LDD A,(HL) case 3: // GB: LDD A,(HL)
A() = busRead(HL()--); A() = IntelProcessor::memoryRead(HL()--);
tick(2); tick(2);
break; break;
default: default:
@@ -642,7 +642,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
tick(2); tick(2);
break; break;
case 4: // GB: LD (FF00 + n),A case 4: // GB: LD (FF00 + n),A
busWrite(IoRegisters::BASE + fetchByte(), A()); IntelProcessor::memoryWrite(IoRegisters::BASE + fetchByte(), A());
tick(3); tick(3);
break; break;
case 5: { // GB: ADD SP,dd case 5: { // GB: ADD SP,dd
@@ -658,7 +658,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
tick(4); tick(4);
break; break;
case 6: // GB: LD A,(FF00 + n) case 6: // GB: LD A,(FF00 + n)
A() = busRead(IoRegisters::BASE + fetchByte()); A() = IntelProcessor::memoryRead(IoRegisters::BASE + fetchByte());
tick(3); tick(3);
break; break;
case 7: { // GB: LD HL,SP + dd case 7: { // GB: LD HL,SP + dd
@@ -719,16 +719,16 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
tick(3); tick(3);
break; break;
case 4: // GB: LD (FF00 + C),A case 4: // GB: LD (FF00 + C),A
busWrite(IoRegisters::BASE + C(), A()); IntelProcessor::memoryWrite(IoRegisters::BASE + C(), A());
tick(2); tick(2);
break; break;
case 5: // GB: LD (nn),A case 5: // GB: LD (nn),A
BUS().ADDRESS() = MEMPTR() = fetchWord(); BUS().ADDRESS() = MEMPTR() = fetchWord();
busWrite(A()); IntelProcessor::memoryWrite(A());
tick(4); tick(4);
break; break;
case 6: // GB: LD A,(FF00 + C) case 6: // GB: LD A,(FF00 + C)
A() = busRead(IoRegisters::BASE + C()); A() = IntelProcessor::memoryRead(IoRegisters::BASE + C());
tick(2); tick(2);
break; break;
case 7: // GB: LD A,(nn) case 7: // GB: LD A,(nn)

View File

@@ -140,8 +140,8 @@ namespace EightBit {
void busReadModifyWrite(const uint8_t data) { void busReadModifyWrite(const uint8_t data) {
// The read will have already taken place... // The read will have already taken place...
busWrite(); memoryWrite();
Processor::busWrite(data); memoryWrite(data);
} }
// Instruction implementations // Instruction implementations

View File

@@ -249,30 +249,30 @@ int EightBit::MOS6502::execute() {
case 0x7f: rra(AM_AbsoluteX()); break; // *RRA (absolute, X) case 0x7f: rra(AM_AbsoluteX()); break; // *RRA (absolute, X)
case 0x80: AM_Immediate(); break; // *NOP (immediate) case 0x80: AM_Immediate(); break; // *NOP (immediate)
case 0x81: Processor::busWrite(Address_IndexedIndirectX(), A()); break; // STA (indexed indirect X) case 0x81: memoryWrite(Address_IndexedIndirectX(), A()); break; // STA (indexed indirect X)
case 0x82: AM_Immediate(); break; // *NOP (immediate) case 0x82: AM_Immediate(); break; // *NOP (immediate)
case 0x83: Processor::busWrite(Address_IndexedIndirectX(), A() & X()); break; // *SAX (indexed indirect X) case 0x83: memoryWrite(Address_IndexedIndirectX(), A() & X()); break; // *SAX (indexed indirect X)
case 0x84: Processor::busWrite(Address_ZeroPage(), Y()); break; // STY (zero page) case 0x84: memoryWrite(Address_ZeroPage(), Y()); break; // STY (zero page)
case 0x85: Processor::busWrite(Address_ZeroPage(), A()); break; // STA (zero page) case 0x85: memoryWrite(Address_ZeroPage(), A()); break; // STA (zero page)
case 0x86: Processor::busWrite(Address_ZeroPage(), X()); break; // STX (zero page) case 0x86: memoryWrite(Address_ZeroPage(), X()); break; // STX (zero page)
case 0x87: Processor::busWrite(Address_ZeroPage(), A() & X()); break; // *SAX (zero page) case 0x87: memoryWrite(Address_ZeroPage(), A() & X()); break; // *SAX (zero page)
case 0x88: busRead(); Y() = dec(Y()); break; // DEY (implied) case 0x88: busRead(); Y() = dec(Y()); break; // DEY (implied)
case 0x89: AM_Immediate(); break; // *NOP (immediate) case 0x89: AM_Immediate(); break; // *NOP (immediate)
case 0x8a: busRead(); A() = through(X()); break; // TXA (implied) case 0x8a: busRead(); A() = through(X()); break; // TXA (implied)
case 0x8b: break; case 0x8b: break;
case 0x8c: Processor::busWrite(Address_Absolute(), Y()); break; // STY (absolute) case 0x8c: memoryWrite(Address_Absolute(), Y()); break; // STY (absolute)
case 0x8d: Processor::busWrite(Address_Absolute(), A()); break; // STA (absolute) case 0x8d: memoryWrite(Address_Absolute(), A()); break; // STA (absolute)
case 0x8e: Processor::busWrite(Address_Absolute(), X()); break; // STX (absolute) case 0x8e: memoryWrite(Address_Absolute(), X()); break; // STX (absolute)
case 0x8f: Processor::busWrite(Address_Absolute(), A() & X()); break; // *SAX (absolute) case 0x8f: memoryWrite(Address_Absolute(), A() & X()); break; // *SAX (absolute)
case 0x90: branch(!carry()); break; // BCC (relative) case 0x90: branch(!carry()); break; // BCC (relative)
case 0x91: AM_IndirectIndexedY(); Processor::busWrite(A()); break; // STA (indirect indexed Y) case 0x91: AM_IndirectIndexedY(); memoryWrite(A()); break; // STA (indirect indexed Y)
case 0x92: break; case 0x92: break;
case 0x93: break; case 0x93: break;
case 0x94: Processor::busWrite(Address_ZeroPageX(), Y()); break; // STY (zero page, X) case 0x94: memoryWrite(Address_ZeroPageX(), Y()); break; // STY (zero page, X)
case 0x95: Processor::busWrite(Address_ZeroPageX(), A()); break; // STA (zero page, X) case 0x95: memoryWrite(Address_ZeroPageX(), A()); break; // STA (zero page, X)
case 0x96: Processor::busWrite(Address_ZeroPageY(), X()); break; // STX (zero page, Y) case 0x96: memoryWrite(Address_ZeroPageY(), X()); break; // STX (zero page, Y)
case 0x97: Processor::busWrite(Address_ZeroPageY(), A() & X()); break; // *SAX (zero page, Y) case 0x97: memoryWrite(Address_ZeroPageY(), A() & X()); break; // *SAX (zero page, Y)
case 0x98: busRead(); A() = through(Y()); break; // TYA (implied) case 0x98: busRead(); A() = through(Y()); break; // TYA (implied)
case 0x99: sta_AbsoluteY(); break; // STA (absolute, Y) case 0x99: sta_AbsoluteY(); break; // STA (absolute, Y)
case 0x9a: busRead(); S() = X(); break; // TXS (implied) case 0x9a: busRead(); S() = X(); break; // TXS (implied)
@@ -426,13 +426,13 @@ EightBit::register16_t EightBit::MOS6502::Address_Indirect() {
uint8_t EightBit::MOS6502::Address_ZeroPageX() { uint8_t EightBit::MOS6502::Address_ZeroPageX() {
const auto address = Address_ZeroPage(); const auto address = Address_ZeroPage();
Processor::busRead(address); memoryRead(address);
return address + X(); return address + X();
} }
uint8_t EightBit::MOS6502::Address_ZeroPageY() { uint8_t EightBit::MOS6502::Address_ZeroPageY() {
const auto address = Address_ZeroPage(); const auto address = Address_ZeroPage();
Processor::busRead(address); memoryRead(address);
return address + Y(); return address + Y();
} }
@@ -472,18 +472,18 @@ uint8_t EightBit::MOS6502::AM_Immediate() {
} }
uint8_t EightBit::MOS6502::AM_Absolute() { uint8_t EightBit::MOS6502::AM_Absolute() {
return Processor::busRead(Address_Absolute()); return memoryRead(Address_Absolute());
} }
uint8_t EightBit::MOS6502::AM_ZeroPage() { uint8_t EightBit::MOS6502::AM_ZeroPage() {
return Processor::busRead(Address_ZeroPage()); return memoryRead(Address_ZeroPage());
} }
uint8_t EightBit::MOS6502::AM_AbsoluteX(const PageCrossingBehavior behaviour) { uint8_t EightBit::MOS6502::AM_AbsoluteX(const PageCrossingBehavior behaviour) {
const auto [address, page] = Address_AbsoluteX(); const auto [address, page] = Address_AbsoluteX();
auto possible = getBytePaged(page, address.low); auto possible = getBytePaged(page, address.low);
if ((behaviour == PageCrossingBehavior::AlwaysReadTwice) || UNLIKELY(page != address.high)) if ((behaviour == PageCrossingBehavior::AlwaysReadTwice) || UNLIKELY(page != address.high))
possible = Processor::busRead(address); possible = memoryRead(address);
return possible; return possible;
} }
@@ -491,27 +491,27 @@ uint8_t EightBit::MOS6502::AM_AbsoluteY() {
const auto[address, page] = Address_AbsoluteY(); const auto[address, page] = Address_AbsoluteY();
auto possible = getBytePaged(page, address.low); auto possible = getBytePaged(page, address.low);
if (UNLIKELY(page != address.high)) if (UNLIKELY(page != address.high))
possible = Processor::busRead(address); possible = memoryRead(address);
return possible; return possible;
} }
uint8_t EightBit::MOS6502::AM_ZeroPageX() { uint8_t EightBit::MOS6502::AM_ZeroPageX() {
return Processor::busRead(Address_ZeroPageX()); return memoryRead(Address_ZeroPageX());
} }
uint8_t EightBit::MOS6502::AM_ZeroPageY() { uint8_t EightBit::MOS6502::AM_ZeroPageY() {
return Processor::busRead(Address_ZeroPageY()); return memoryRead(Address_ZeroPageY());
} }
uint8_t EightBit::MOS6502::AM_IndexedIndirectX() { uint8_t EightBit::MOS6502::AM_IndexedIndirectX() {
return Processor::busRead(Address_IndexedIndirectX()); return memoryRead(Address_IndexedIndirectX());
} }
uint8_t EightBit::MOS6502::AM_IndirectIndexedY() { uint8_t EightBit::MOS6502::AM_IndirectIndexedY() {
const auto [address, page] = Address_IndirectIndexedY(); const auto [address, page] = Address_IndirectIndexedY();
auto possible = getBytePaged(page, address.low); auto possible = getBytePaged(page, address.low);
if (page != address.high) if (page != address.high)
possible = Processor::busRead(address); possible = memoryRead(address);
return possible; return possible;
} }
@@ -524,7 +524,7 @@ void EightBit::MOS6502::branch(const int condition) {
const auto page = PC().high; const auto page = PC().high;
jump(destination); jump(destination);
if (UNLIKELY(PC().high != page)) if (UNLIKELY(PC().high != page))
Processor::busRead(register16_t(PC().low, page)); memoryRead(register16_t(PC().low, page));
} }
} }
@@ -748,11 +748,11 @@ void EightBit::MOS6502::sre(const uint8_t value) {
void EightBit::MOS6502::sta_AbsoluteX() { void EightBit::MOS6502::sta_AbsoluteX() {
const auto [address, page] = Address_AbsoluteX(); const auto [address, page] = Address_AbsoluteX();
getBytePaged(page, address.low); getBytePaged(page, address.low);
Processor::busWrite(address, A()); memoryWrite(address, A());
} }
void EightBit::MOS6502::sta_AbsoluteY() { void EightBit::MOS6502::sta_AbsoluteY() {
const auto [address, page] = Address_AbsoluteY(); const auto [address, page] = Address_AbsoluteY();
getBytePaged(page, address.low); getBytePaged(page, address.low);
Processor::busWrite(address, A()); memoryWrite(address, A());
} }

View File

@@ -178,18 +178,18 @@ void EightBit::mc6809::executeUnprefixed() {
case 0x1c: tick(3); CC() &= AM_immediate_byte(); break; // AND (ANDCC immediate) case 0x1c: tick(3); CC() &= AM_immediate_byte(); break; // AND (ANDCC immediate)
// ASL/LSL // ASL/LSL
case 0x08: tick(6); Processor::busWrite(asl(AM_direct_byte())); break; // ASL (direct) case 0x08: tick(6); memoryWrite(asl(AM_direct_byte())); break; // ASL (direct)
case 0x48: tick(2); A() = asl(A()); break; // ASL (ASLA inherent) case 0x48: tick(2); A() = asl(A()); break; // ASL (ASLA inherent)
case 0x58: tick(2); B() = asl(B()); break; // ASL (ASLB inherent) case 0x58: tick(2); B() = asl(B()); break; // ASL (ASLB inherent)
case 0x68: tick(6); Processor::busWrite(asl(AM_indexed_byte())); break; // ASL (indexed) case 0x68: tick(6); memoryWrite(asl(AM_indexed_byte())); break; // ASL (indexed)
case 0x78: tick(7); Processor::busWrite(asl(AM_extended_byte())); break; // ASL (extended) case 0x78: tick(7); memoryWrite(asl(AM_extended_byte())); break; // ASL (extended)
// ASR // ASR
case 0x07: tick(6); Processor::busWrite(asr(AM_direct_byte())); break; // ASR (direct) case 0x07: tick(6); memoryWrite(asr(AM_direct_byte())); break; // ASR (direct)
case 0x47: tick(2); A() = asr(A()); break; // ASR (ASRA inherent) case 0x47: tick(2); A() = asr(A()); break; // ASR (ASRA inherent)
case 0x57: tick(2); B() = asr(B()); break; // ASR (ASRB inherent) case 0x57: tick(2); B() = asr(B()); break; // ASR (ASRB inherent)
case 0x67: tick(6); Processor::busWrite(asr(AM_indexed_byte())); break; // ASR (indexed) case 0x67: tick(6); memoryWrite(asr(AM_indexed_byte())); break; // ASR (indexed)
case 0x77: tick(7); Processor::busWrite(asr(AM_extended_byte())); break; // ASR (extended) case 0x77: tick(7); memoryWrite(asr(AM_extended_byte())); break; // ASR (extended)
// BIT // BIT
case 0x85: tick(2); bit(A(), AM_immediate_byte()); break; // BIT (BITA immediate) case 0x85: tick(2); bit(A(), AM_immediate_byte()); break; // BIT (BITA immediate)
@@ -203,11 +203,11 @@ void EightBit::mc6809::executeUnprefixed() {
case 0xf5: tick(5); bit(B(), AM_extended_byte()); break; // BIT (BITB extended) case 0xf5: tick(5); bit(B(), AM_extended_byte()); break; // BIT (BITB extended)
// CLR // CLR
case 0x0f: tick(6); Processor::busWrite(Address_direct(), clr()); break; // CLR (direct) case 0x0f: tick(6); memoryWrite(Address_direct(), clr()); break; // CLR (direct)
case 0x4f: tick(2); A() = clr(); break; // CLR (CLRA implied) case 0x4f: tick(2); A() = clr(); break; // CLR (CLRA implied)
case 0x5f: tick(2); B() = clr(); break; // CLR (CLRB implied) case 0x5f: tick(2); B() = clr(); break; // CLR (CLRB implied)
case 0x6f: tick(6); Processor::busWrite(Address_indexed(), clr()); break; // CLR (indexed) case 0x6f: tick(6); memoryWrite(Address_indexed(), clr()); break; // CLR (indexed)
case 0x7f: tick(7); Processor::busWrite(Address_extended(), clr()); break; // CLR (extended) case 0x7f: tick(7); memoryWrite(Address_extended(), clr()); break; // CLR (extended)
// CMP // CMP
@@ -230,11 +230,11 @@ void EightBit::mc6809::executeUnprefixed() {
case 0xbc: tick(7); cmp(X(), AM_extended_word()); break; // CMP (CMPX, extended) case 0xbc: tick(7); cmp(X(), AM_extended_word()); break; // CMP (CMPX, extended)
// COM // COM
case 0x03: tick(6); Processor::busWrite(com(AM_direct_byte())); break; // COM (direct) case 0x03: tick(6); memoryWrite(com(AM_direct_byte())); break; // COM (direct)
case 0x43: tick(2); A() = com(A()); break; // COM (COMA inherent) case 0x43: tick(2); A() = com(A()); break; // COM (COMA inherent)
case 0x53: tick(2); B() = com(B()); break; // COM (COMB inherent) case 0x53: tick(2); B() = com(B()); break; // COM (COMB inherent)
case 0x63: tick(6); Processor::busWrite(com(AM_indexed_byte())); break; // COM (indexed) case 0x63: tick(6); memoryWrite(com(AM_indexed_byte())); break; // COM (indexed)
case 0x73: tick(7); Processor::busWrite(com(AM_extended_byte())); break; // COM (extended) case 0x73: tick(7); memoryWrite(com(AM_extended_byte())); break; // COM (extended)
// CWAI // CWAI
case 0x3c: tick(11); cwai(AM_direct_byte()); break; // CWAI (direct) case 0x3c: tick(11); cwai(AM_direct_byte()); break; // CWAI (direct)
@@ -243,11 +243,11 @@ void EightBit::mc6809::executeUnprefixed() {
case 0x19: tick(2); A() = da(A()); break; // DAA (inherent) case 0x19: tick(2); A() = da(A()); break; // DAA (inherent)
// DEC // DEC
case 0x0a: tick(6); Processor::busWrite(dec(AM_direct_byte())); break; // DEC (direct) case 0x0a: tick(6); memoryWrite(dec(AM_direct_byte())); break; // DEC (direct)
case 0x4a: tick(2); A() = dec(A()); break; // DEC (DECA inherent) case 0x4a: tick(2); A() = dec(A()); break; // DEC (DECA inherent)
case 0x5a: tick(2); B() = dec(B()); break; // DEC (DECB inherent) case 0x5a: tick(2); B() = dec(B()); break; // DEC (DECB inherent)
case 0x6a: tick(6); Processor::busWrite(dec(AM_indexed_byte())); break; // DEC (indexed) case 0x6a: tick(6); memoryWrite(dec(AM_indexed_byte())); break; // DEC (indexed)
case 0x7a: tick(7); Processor::busWrite(dec(AM_extended_byte())); break; // DEC (extended) case 0x7a: tick(7); memoryWrite(dec(AM_extended_byte())); break; // DEC (extended)
// EOR // EOR
@@ -267,11 +267,11 @@ void EightBit::mc6809::executeUnprefixed() {
case 0x1e: tick(8); exg(AM_immediate_byte()); break; // EXG (R1,R2 immediate) case 0x1e: tick(8); exg(AM_immediate_byte()); break; // EXG (R1,R2 immediate)
// INC // INC
case 0x0c: tick(6); Processor::busWrite(inc(AM_direct_byte())); break; // INC (direct) case 0x0c: tick(6); memoryWrite(inc(AM_direct_byte())); break; // INC (direct)
case 0x4c: tick(2); A() = inc(A()); break; // INC (INCA inherent) case 0x4c: tick(2); A() = inc(A()); break; // INC (INCA inherent)
case 0x5c: tick(2); B() = inc(B()); break; // INC (INCB inherent) case 0x5c: tick(2); B() = inc(B()); break; // INC (INCB inherent)
case 0x6c: tick(6); Processor::busWrite(inc(AM_indexed_byte())); break; // INC (indexed) case 0x6c: tick(6); memoryWrite(inc(AM_indexed_byte())); break; // INC (indexed)
case 0x7c: tick(7); Processor::busWrite(inc(AM_extended_byte())); break; // INC (extended) case 0x7c: tick(7); memoryWrite(inc(AM_extended_byte())); break; // INC (extended)
// JMP // JMP
case 0x0e: tick(6); jump(Address_direct()); break; // JMP (direct) case 0x0e: tick(6); jump(Address_direct()); break; // JMP (direct)
@@ -322,21 +322,21 @@ void EightBit::mc6809::executeUnprefixed() {
case 0x33: tick(4); U() = Address_indexed(); break; // LEA (LEAU indexed) case 0x33: tick(4); U() = Address_indexed(); break; // LEA (LEAU indexed)
// LSR // LSR
case 0x04: tick(6); Processor::busWrite(lsr(AM_direct_byte())); break; // LSR (direct) case 0x04: tick(6); memoryWrite(lsr(AM_direct_byte())); break; // LSR (direct)
case 0x44: tick(2); A() = lsr(A()); break; // LSR (LSRA inherent) case 0x44: tick(2); A() = lsr(A()); break; // LSR (LSRA inherent)
case 0x54: tick(2); B() = lsr(B()); break; // LSR (LSRB inherent) case 0x54: tick(2); B() = lsr(B()); break; // LSR (LSRB inherent)
case 0x64: tick(6); Processor::busWrite(lsr(AM_indexed_byte())); break; // LSR (indexed) case 0x64: tick(6); memoryWrite(lsr(AM_indexed_byte())); break; // LSR (indexed)
case 0x74: tick(7); Processor::busWrite(lsr(AM_extended_byte())); break; // LSR (extended) case 0x74: tick(7); memoryWrite(lsr(AM_extended_byte())); break; // LSR (extended)
// MUL // MUL
case 0x3d: tick(11); D() = mul(A(), B()); break; // MUL (inherent) case 0x3d: tick(11); D() = mul(A(), B()); break; // MUL (inherent)
// NEG // NEG
case 0x00: tick(6); Processor::busWrite(neg(AM_direct_byte())); break; // NEG (direct) case 0x00: tick(6); memoryWrite(neg(AM_direct_byte())); break; // NEG (direct)
case 0x40: tick(2); A() = neg(A()); break; // NEG (NEGA, inherent) case 0x40: tick(2); A() = neg(A()); break; // NEG (NEGA, inherent)
case 0x50: tick(2); B() = neg(B()); break; // NEG (NEGB, inherent) case 0x50: tick(2); B() = neg(B()); break; // NEG (NEGB, inherent)
case 0x60: tick(6); Processor::busWrite(neg(AM_indexed_byte())); break; // NEG (indexed) case 0x60: tick(6); memoryWrite(neg(AM_indexed_byte())); break; // NEG (indexed)
case 0x70: tick(7); Processor::busWrite(neg(AM_extended_byte())); break; // NEG (extended) case 0x70: tick(7); memoryWrite(neg(AM_extended_byte())); break; // NEG (extended)
// NOP // NOP
case 0x12: tick(2); break; // NOP (inherent) case 0x12: tick(2); break; // NOP (inherent)
@@ -367,18 +367,18 @@ void EightBit::mc6809::executeUnprefixed() {
case 0x37: tick(5); pul(U(), AM_immediate_byte()); break; // PUL (PULU immediate) case 0x37: tick(5); pul(U(), AM_immediate_byte()); break; // PUL (PULU immediate)
// ROL // ROL
case 0x09: tick(6); Processor::busWrite(rol(AM_direct_byte())); break; // ROL (direct) case 0x09: tick(6); memoryWrite(rol(AM_direct_byte())); break; // ROL (direct)
case 0x49: tick(2); A() = rol(A()); break; // ROL (ROLA inherent) case 0x49: tick(2); A() = rol(A()); break; // ROL (ROLA inherent)
case 0x59: tick(2); B() = rol(B()); break; // ROL (ROLB inherent) case 0x59: tick(2); B() = rol(B()); break; // ROL (ROLB inherent)
case 0x69: tick(6); Processor::busWrite(rol(AM_indexed_byte())); break; // ROL (indexed) case 0x69: tick(6); memoryWrite(rol(AM_indexed_byte())); break; // ROL (indexed)
case 0x79: tick(7); Processor::busWrite(rol(AM_extended_byte())); break; // ROL (extended) case 0x79: tick(7); memoryWrite(rol(AM_extended_byte())); break; // ROL (extended)
// ROR // ROR
case 0x06: tick(6); Processor::busWrite(ror(AM_direct_byte())); break; // ROR (direct) case 0x06: tick(6); memoryWrite(ror(AM_direct_byte())); break; // ROR (direct)
case 0x46: tick(2); A() = ror(A()); break; // ROR (RORA inherent) case 0x46: tick(2); A() = ror(A()); break; // ROR (RORA inherent)
case 0x56: tick(2); B() = ror(B()); break; // ROR (RORB inherent) case 0x56: tick(2); B() = ror(B()); break; // ROR (RORB inherent)
case 0x66: tick(6); Processor::busWrite(ror(AM_indexed_byte())); break; // ROR (indexed) case 0x66: tick(6); memoryWrite(ror(AM_indexed_byte())); break; // ROR (indexed)
case 0x76: tick(7); Processor::busWrite(ror(AM_extended_byte())); break; // ROR (extended) case 0x76: tick(7); memoryWrite(ror(AM_extended_byte())); break; // ROR (extended)
// RTI // RTI
case 0x3B: tick(6); rti(); break; // RTI (inherent) case 0x3B: tick(6); rti(); break; // RTI (inherent)
@@ -406,14 +406,14 @@ void EightBit::mc6809::executeUnprefixed() {
// ST // ST
// STA // STA
case 0x97: tick(4); Processor::busWrite(Address_direct(), st(A())); break; // ST (STA direct) case 0x97: tick(4); memoryWrite(Address_direct(), st(A())); break; // ST (STA direct)
case 0xa7: tick(4); Processor::busWrite(Address_indexed(), st(A())); break; // ST (STA indexed) case 0xa7: tick(4); memoryWrite(Address_indexed(), st(A())); break; // ST (STA indexed)
case 0xb7: tick(5); Processor::busWrite(Address_extended(), st(A())); break; // ST (STA extended) case 0xb7: tick(5); memoryWrite(Address_extended(), st(A())); break; // ST (STA extended)
// STB // STB
case 0xd7: tick(4); Processor::busWrite(Address_direct(), st(B())); break; // ST (STB direct) case 0xd7: tick(4); memoryWrite(Address_direct(), st(B())); break; // ST (STB direct)
case 0xe7: tick(4); Processor::busWrite(Address_indexed(), st(B())); break; // ST (STB indexed) case 0xe7: tick(4); memoryWrite(Address_indexed(), st(B())); break; // ST (STB indexed)
case 0xf7: tick(5); Processor::busWrite(Address_extended(), st(B())); break; // ST (STB extended) case 0xf7: tick(5); memoryWrite(Address_extended(), st(B())); break; // ST (STB extended)
// STD // STD
case 0xdd: tick(5); Processor::setWord(Address_direct(), st(D())); break; // ST (STD direct) case 0xdd: tick(5); Processor::setWord(Address_direct(), st(D())); break; // ST (STD direct)
@@ -605,11 +605,11 @@ uint8_t EightBit::mc6809::pop() {
} }
void EightBit::mc6809::push(register16_t& stack, const uint8_t value) { void EightBit::mc6809::push(register16_t& stack, const uint8_t value) {
Processor::busWrite(--stack, value); memoryWrite(--stack, value);
} }
uint8_t EightBit::mc6809::pop(register16_t& stack) { uint8_t EightBit::mc6809::pop(register16_t& stack) {
return Processor::busRead(stack++); return memoryRead(stack++);
} }
// //
@@ -733,15 +733,15 @@ uint8_t EightBit::mc6809::AM_immediate_byte() {
} }
uint8_t EightBit::mc6809::AM_direct_byte() { uint8_t EightBit::mc6809::AM_direct_byte() {
return Processor::busRead(Address_direct()); return memoryRead(Address_direct());
} }
uint8_t EightBit::mc6809::AM_indexed_byte() { uint8_t EightBit::mc6809::AM_indexed_byte() {
return Processor::busRead(Address_indexed()); return memoryRead(Address_indexed());
} }
uint8_t EightBit::mc6809::AM_extended_byte() { uint8_t EightBit::mc6809::AM_extended_byte() {
return Processor::busRead(Address_extended()); return memoryRead(Address_extended());
} }
// //

View File

@@ -2,12 +2,13 @@
#include "FuseTestRunner.h" #include "FuseTestRunner.h"
#include "Disassembler.h" #include "Disassembler.h"
#include <stdexcept>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& result) Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& result)
: m_test(test), : m_test(test),
m_result(result), m_result(result),
m_cpu(*this, m_ports), m_cpu(*this),
m_totalCycles(0) { m_totalCycles(0) {
for (const auto& event : m_result.events.events) { for (const auto& event : m_result.events.events) {
@@ -20,20 +21,27 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& result)
}); });
ReadByte.connect([this](EightBit::EventArgs&) { ReadByte.connect([this](EightBit::EventArgs&) {
addActualEvent("MR"); addActualEvent(currentBusAccessType() + "R");
}); });
WrittenByte.connect([this](EightBit::EventArgs&) { WrittenByte.connect([this](EightBit::EventArgs&) {
addActualEvent("MW"); addActualEvent(currentBusAccessType() + "W");
}); });
}
m_ports.ReadPort.connect([this](uint8_t port) { std::string Fuse::TestRunner::currentBusAccessType() {
addActualEvent("PR");
});
m_ports.WrittenPort.connect([this](uint8_t port) { const bool ioRequest = m_cpu.requestingIO();
addActualEvent("PW"); const bool memoryRequest = m_cpu.requestingMemory();
}); if (ioRequest && memoryRequest)
throw std::logic_error("Invalid bus state (both IORQ and MREQ lowered");
if (ioRequest)
return "P";
if (memoryRequest)
return "M";
throw std::logic_error("Invalid bus state (neither IORQ and MREQ lowered");
} }
void Fuse::TestRunner::addActualEvent(const std::string& specifier) { void Fuse::TestRunner::addActualEvent(const std::string& specifier) {
@@ -62,6 +70,39 @@ void Fuse::TestRunner::lowerPOWER() {
EightBit::Bus::lowerPOWER(); EightBit::Bus::lowerPOWER();
} }
EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) {
const bool memory = m_cpu.requestingMemory();
if (memory)
return {
m_ram,
0x0000,
0xffff,
EightBit::MemoryMapping::AccessLevel::ReadWrite
};
const bool io = m_cpu.requestingIO();
if (io) {
m_ports.setAccessType(EightBit::InputOutput::AccessType::Unknown);
const bool reading = m_cpu.requestingRead();
if (reading)
m_ports.setAccessType(EightBit::InputOutput::AccessType::Reading);
const bool writing = m_cpu.requestingWrite();
if (writing)
m_ports.setAccessType(EightBit::InputOutput::AccessType::Writing);
return {
m_ports,
0x0000,
0xff,
EightBit::MemoryMapping::AccessLevel::ReadWrite
};
}
}
void Fuse::TestRunner::initialise() { void Fuse::TestRunner::initialise() {
initialiseMemory(); initialiseMemory();
} }
@@ -102,7 +143,7 @@ void Fuse::TestRunner::initialiseMemory() {
auto address = memoryDatum.address; auto address = memoryDatum.address;
auto bytes = memoryDatum.bytes; auto bytes = memoryDatum.bytes;
for (int i = 0; i < bytes.size(); ++i) for (int i = 0; i < bytes.size(); ++i)
poke(address + i, bytes[i]); m_ram.poke(address + i, bytes[i]);
} }
} }
@@ -350,7 +391,7 @@ void Fuse::TestRunner::checkMemory() {
for (int i = 0; i < bytes.size(); ++i) { for (int i = 0; i < bytes.size(); ++i) {
auto expected = bytes[i]; auto expected = bytes[i];
uint16_t address = memoryDatum.address + i; uint16_t address = memoryDatum.address + i;
auto actual = peek(address); auto actual = m_ram.peek(address);
if (expected != actual) { if (expected != actual) {
m_failed = true; m_failed = true;
if (first) { if (first) {

View File

@@ -40,6 +40,7 @@ namespace Fuse {
const std::string& lowDescription, const std::string& lowDescription,
EightBit::register16_t actual, EightBit::register16_t expected) const; EightBit::register16_t actual, EightBit::register16_t expected) const;
std::string currentBusAccessType();
void addActualEvent(const std::string& specifier); void addActualEvent(const std::string& specifier);
void dumpExpectedEvents() const; void dumpExpectedEvents() const;
void dumpActualEvents() const; void dumpActualEvents() const;
@@ -48,9 +49,7 @@ namespace Fuse {
static void dumpEvent(const TestEvent& event); static void dumpEvent(const TestEvent& event);
protected: protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) final { virtual EightBit::MemoryMapping mapping(uint16_t address) final;
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
}
public: public:
TestRunner(const Test& test, const ExpectedTestResult& expected); TestRunner(const Test& test, const ExpectedTestResult& expected);

View File

@@ -5,7 +5,6 @@
#include <stdexcept> #include <stdexcept>
#include <Bus.h> #include <Bus.h>
#include <InputOutput.h>
#include <IntelProcessor.h> #include <IntelProcessor.h>
#include <EventArgs.h> #include <EventArgs.h>
#include <Signal.h> #include <Signal.h>
@@ -47,12 +46,11 @@ namespace EightBit {
CF = Bit0, CF = Bit0,
}; };
Z80(Bus& bus, InputOutput& ports); Z80(Bus& bus);
Signal<Z80> ExecutingInstruction; Signal<Z80> ExecutingInstruction;
Signal<Z80> ExecutedInstruction; Signal<Z80> ExecutedInstruction;
int execute(uint8_t opcode) { return IntelProcessor::execute(opcode); }
int execute() final; int execute() final;
int step() final; int step() final;
@@ -95,6 +93,12 @@ namespace EightBit {
m_accumulatorFlagsSet ^= 1; m_accumulatorFlagsSet ^= 1;
} }
bool requestingIO() { return lowered(IORQ()); }
bool requestingMemory() { return lowered(MREQ()); }
bool requestingRead() { return lowered(RD()); }
bool requestingWrite() { return lowered(WR()); }
DECLARE_PIN_INPUT(NMI) DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_OUTPUT(M1) DECLARE_PIN_OUTPUT(M1)
@@ -118,12 +122,13 @@ namespace EightBit {
IntelProcessor::pushWord(destination); IntelProcessor::pushWord(destination);
} }
void memoryWrite() final;
uint8_t memoryRead() final;
void busWrite() final; void busWrite() final;
uint8_t busRead() final; uint8_t busRead() final;
private: private:
InputOutput& m_ports;
enum { BC_IDX, DE_IDX, HL_IDX }; enum { BC_IDX, DE_IDX, HL_IDX };
std::array<std::array<register16_t, 3>, 2> m_registers; std::array<std::array<register16_t, 3>, 2> m_registers;
@@ -176,10 +181,9 @@ namespace EightBit {
uint8_t readInitialOpCode() { uint8_t readInitialOpCode() {
tick(); tick();
lowerM1(); lowerM1();
const auto returned = IntelProcessor::busRead(PC()); const auto returned = IntelProcessor::memoryRead(PC());
raiseM1(); raiseM1();
BUS().ADDRESS().low = REFRESH(); BUS().ADDRESS() = { REFRESH(), IV() };
BUS().ADDRESS().high = IV();
lowerRFSH(); lowerRFSH();
lowerMREQ(); lowerMREQ();
raiseMREQ(); raiseMREQ();
@@ -253,7 +257,7 @@ namespace EightBit {
case 5: case 5:
return HL2().low; return HL2().low;
case 6: case 6:
return IntelProcessor::busRead(UNLIKELY(m_displaced) ? displacedAddress() : HL().word); return IntelProcessor::memoryRead(UNLIKELY(m_displaced) ? displacedAddress() : HL().word);
case 7: case 7:
return A(); return A();
default: default:
@@ -284,7 +288,7 @@ namespace EightBit {
HL2().low = value; HL2().low = value;
break; break;
case 6: case 6:
IntelProcessor::busWrite(UNLIKELY(m_displaced) ? displacedAddress() : HL().word, value); IntelProcessor::memoryWrite(UNLIKELY(m_displaced) ? displacedAddress() : HL().word, value);
break; break;
case 7: case 7:
A() = value; A() = value;
@@ -317,7 +321,7 @@ namespace EightBit {
L() = value; L() = value;
break; break;
case 6: case 6:
IntelProcessor::busWrite(HL(), value); IntelProcessor::memoryWrite(HL(), value);
break; break;
case 7: case 7:
A() = value; A() = value;
@@ -446,10 +450,10 @@ namespace EightBit {
void rrd(uint8_t& f, register16_t address, uint8_t& update); void rrd(uint8_t& f, register16_t address, uint8_t& update);
void rld(uint8_t& f, register16_t address, uint8_t& update); void rld(uint8_t& f, register16_t address, uint8_t& update);
void writePort(uint8_t port); void portWrite(uint8_t port);
void writePort(); void portWrite();
uint8_t readPort(uint8_t port); uint8_t portRead(uint8_t port);
uint8_t readPort(); uint8_t portRead();
}; };
} }

View File

@@ -3,9 +3,8 @@
// based on http://www.z80.info/decoding.htm // based on http://www.z80.info/decoding.htm
EightBit::Z80::Z80(Bus& bus, InputOutput& ports) EightBit::Z80::Z80(Bus& bus)
: IntelProcessor(bus), : IntelProcessor(bus) {
m_ports(ports) {
RaisedPOWER.connect([this](EventArgs) { RaisedPOWER.connect([this](EventArgs) {
raiseM1(); raiseM1();
@@ -58,22 +57,33 @@ EightBit::register16_t& EightBit::Z80::HL() {
return m_registers[m_registerSet][HL_IDX]; return m_registers[m_registerSet][HL_IDX];
} }
void EightBit::Z80::busWrite() { void EightBit::Z80::memoryWrite() {
tick(3); tick(2);
lowerMREQ(); lowerMREQ();
lowerWR(); IntelProcessor::memoryWrite();
IntelProcessor::busWrite();
raiseWR();
raiseMREQ(); raiseMREQ();
} }
uint8_t EightBit::Z80::busRead() { uint8_t EightBit::Z80::memoryRead() {
tick(3); tick(2);
lowerMREQ(); lowerMREQ();
const auto returned = IntelProcessor::memoryRead();
raiseMREQ();
return returned;
}
void EightBit::Z80::busWrite() {
tick();
lowerWR();
IntelProcessor::busWrite();
raiseWR();
}
uint8_t EightBit::Z80::busRead() {
tick();
lowerRD(); lowerRD();
const auto returned = IntelProcessor::busRead(); const auto returned = IntelProcessor::busRead();
raiseRD(); raiseRD();
raiseMREQ();
return returned; return returned;
} }
@@ -107,7 +117,7 @@ void EightBit::Z80::handleINT() {
tick(5); tick(5);
switch (IM()) { switch (IM()) {
case 0: // i8080 equivalent case 0: // i8080 equivalent
execute(data); IntelProcessor::execute(data);
break; break;
case 1: case 1:
tick(); tick();
@@ -481,20 +491,20 @@ void EightBit::Z80::ccf(uint8_t& f, const uint8_t operand) {
} }
void EightBit::Z80::xhtl(register16_t& exchange) { void EightBit::Z80::xhtl(register16_t& exchange) {
MEMPTR().low = IntelProcessor::busRead(SP()); MEMPTR().low = IntelProcessor::memoryRead(SP());
++BUS().ADDRESS(); ++BUS().ADDRESS();
MEMPTR().high = busRead(); MEMPTR().high = memoryRead();
tick(); tick();
IntelProcessor::busWrite(exchange.high); IntelProcessor::memoryWrite(exchange.high);
exchange.high = MEMPTR().high; exchange.high = MEMPTR().high;
--BUS().ADDRESS(); --BUS().ADDRESS();
IntelProcessor::busWrite(exchange.low); IntelProcessor::memoryWrite(exchange.low);
exchange.low = MEMPTR().low; exchange.low = MEMPTR().low;
} }
void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register16_t source, register16_t& counter) { void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register16_t source, register16_t& counter) {
const auto contents = IntelProcessor::busRead(source); const auto contents = IntelProcessor::memoryRead(source);
uint8_t result = value - contents; uint8_t result = value - contents;
f = setBit(f, PF, --counter.word); f = setBit(f, PF, --counter.word);
@@ -530,8 +540,8 @@ bool EightBit::Z80::cpdr(uint8_t& f, uint8_t value) {
} }
void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t source, const register16_t destination, register16_t& counter) { void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t source, const register16_t destination, register16_t& counter) {
const auto value = IntelProcessor::busRead(source); const auto value = IntelProcessor::memoryRead(source);
IntelProcessor::busWrite(destination, value); IntelProcessor::memoryWrite(destination, value);
const auto xy = a + value; const auto xy = a + value;
f = setBit(f, XF, xy & Bit3); f = setBit(f, XF, xy & Bit3);
f = setBit(f, YF, xy & Bit1); f = setBit(f, YF, xy & Bit1);
@@ -560,9 +570,9 @@ bool EightBit::Z80::lddr(uint8_t& f, const uint8_t a) {
void EightBit::Z80::blockIn(register16_t& source, const register16_t destination) { void EightBit::Z80::blockIn(register16_t& source, const register16_t destination) {
MEMPTR() = BUS().ADDRESS() = source; MEMPTR() = BUS().ADDRESS() = source;
tick(); tick();
const auto value = readPort(); const auto value = portRead();
tick(3); tick(3);
IntelProcessor::busWrite(destination, value); IntelProcessor::memoryWrite(destination, value);
source.high = decrement(F(), source.high); source.high = decrement(F(), source.high);
F() = setBit(F(), NF); F() = setBit(F(), NF);
} }
@@ -589,10 +599,10 @@ bool EightBit::Z80::indr() {
void EightBit::Z80::blockOut(const register16_t source, register16_t& destination) { void EightBit::Z80::blockOut(const register16_t source, register16_t& destination) {
tick(); tick();
const auto value = IntelProcessor::busRead(source); const auto value = IntelProcessor::memoryRead(source);
destination.high = decrement(F(), destination.high); destination.high = decrement(F(), destination.high);
BUS().ADDRESS() = destination; BUS().ADDRESS() = destination;
writePort(); portWrite();
MEMPTR() = destination; MEMPTR() = destination;
F() = setBit(F(), NF, value & Bit7); F() = setBit(F(), NF, value & Bit7);
F() = setBit(F(), HC | CF, (L() + value) > 0xff); F() = setBit(F(), HC | CF, (L() + value) > 0xff);
@@ -621,9 +631,9 @@ bool EightBit::Z80::otdr() {
void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) { void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) {
(MEMPTR() = BUS().ADDRESS() = address)++; (MEMPTR() = BUS().ADDRESS() = address)++;
const auto memory = busRead(); const auto memory = memoryRead();
tick(4); tick(4);
IntelProcessor::busWrite(promoteNibble(update) | highNibble(memory)); IntelProcessor::memoryWrite(promoteNibble(update) | highNibble(memory));
update = higherNibble(update) | lowerNibble(memory); update = higherNibble(update) | lowerNibble(memory);
f = adjustSZPXY<Z80>(f, update); f = adjustSZPXY<Z80>(f, update);
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
@@ -631,42 +641,36 @@ void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) {
void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) { void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) {
(MEMPTR() = BUS().ADDRESS() = address)++; (MEMPTR() = BUS().ADDRESS() = address)++;
const auto memory = busRead(); const auto memory = memoryRead();
tick(4); tick(4);
IntelProcessor::busWrite(promoteNibble(memory) | lowNibble(update)); IntelProcessor::memoryWrite(promoteNibble(memory) | lowNibble(update));
update = higherNibble(update) | highNibble(memory); update = higherNibble(update) | highNibble(memory);
f = adjustSZPXY<Z80>(f, update); f = adjustSZPXY<Z80>(f, update);
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
} }
void EightBit::Z80::writePort(const uint8_t port) { void EightBit::Z80::portWrite(const uint8_t port) {
MEMPTR() = BUS().ADDRESS() = { port, A() }; MEMPTR() = BUS().ADDRESS() = { port, A() };
BUS().DATA() = A(); BUS().DATA() = A();
writePort(); portWrite();
++MEMPTR().low; ++MEMPTR().low;
} }
void EightBit::Z80::writePort() { void EightBit::Z80::portWrite() {
tick();
lowerIORQ(); lowerIORQ();
lowerWR(); busWrite();
m_ports.write(BUS().ADDRESS().low, BUS().DATA());
raiseWR();
raiseIORQ(); raiseIORQ();
} }
uint8_t EightBit::Z80::readPort(const uint8_t port) { uint8_t EightBit::Z80::portRead(const uint8_t port) {
MEMPTR() = BUS().ADDRESS() = { port, A() }; MEMPTR() = BUS().ADDRESS() = { port, A() };
++MEMPTR().low; ++MEMPTR().low;
return readPort(); return portRead();
} }
uint8_t EightBit::Z80::readPort() { uint8_t EightBit::Z80::portRead() {
tick();
lowerIORQ(); lowerIORQ();
lowerRD(); const auto returned = busRead();
const auto returned = BUS().DATA() = m_ports.read(BUS().ADDRESS().low);
raiseRD();
raiseIORQ(); raiseIORQ();
return returned; return returned;
} }
@@ -706,11 +710,11 @@ int EightBit::Z80::step() {
// CPU.The HALT acknowledge signal is active during this time indicating that the processor // CPU.The HALT acknowledge signal is active during this time indicating that the processor
// is in the HALT state. // is in the HALT state.
const auto discarded = readInitialOpCode(); const auto discarded = readInitialOpCode();
execute(0); // NOP IntelProcessor::execute(0); // NOP
handled = true; handled = true;
} }
if (!handled) if (!handled)
execute(fetchInitialOpCode()); IntelProcessor::execute(fetchInitialOpCode());
} }
ExecutedInstruction.fire(*this); ExecutedInstruction.fire(*this);
return cycles(); return cycles();
@@ -747,7 +751,7 @@ void EightBit::Z80::executeCB(const int x, const int y, const int z) {
uint8_t operand; uint8_t operand;
if (m_displaced) { if (m_displaced) {
tick(2); tick(2);
operand = IntelProcessor::busRead(displacedAddress()); operand = IntelProcessor::memoryRead(displacedAddress());
} else { } else {
operand = R(z); operand = R(z);
} }
@@ -801,7 +805,7 @@ void EightBit::Z80::executeCB(const int x, const int y, const int z) {
if (update) { if (update) {
tick(); tick();
if (m_displaced) { if (m_displaced) {
IntelProcessor::busWrite(operand); IntelProcessor::memoryWrite(operand);
if (!memoryZ) if (!memoryZ)
R2(z, operand); R2(z, operand);
} else { } else {
@@ -820,7 +824,7 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p
switch (z) { switch (z) {
case 0: // Input from port with 16-bit address case 0: // Input from port with 16-bit address
(MEMPTR() = BUS().ADDRESS() = BC())++; (MEMPTR() = BUS().ADDRESS() = BC())++;
readPort(); portRead();
if (y != 6) // IN r[y],(C) if (y != 6) // IN r[y],(C)
R(y, BUS().DATA()); R(y, BUS().DATA());
F() = adjustSZPXY<Z80>(F(), BUS().DATA()); F() = adjustSZPXY<Z80>(F(), BUS().DATA());
@@ -829,7 +833,7 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p
case 1: // Output to port with 16-bit address case 1: // Output to port with 16-bit address
(MEMPTR() = BUS().ADDRESS() = BC())++; (MEMPTR() = BUS().ADDRESS() = BC())++;
BUS().DATA() = y == 6 ? 0 : R(y); BUS().DATA() = y == 6 ? 0 : R(y);
writePort(); portWrite();
break; break;
case 2: // 16-bit add/subtract with carry case 2: // 16-bit add/subtract with carry
switch (q) { switch (q) {
@@ -1080,12 +1084,12 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
case 0: // LD (BC),A case 0: // LD (BC),A
(MEMPTR() = BUS().ADDRESS() = BC())++; (MEMPTR() = BUS().ADDRESS() = BC())++;
MEMPTR().high = BUS().DATA() = A(); MEMPTR().high = BUS().DATA() = A();
busWrite(); memoryWrite();
break; break;
case 1: // LD (DE),A case 1: // LD (DE),A
(MEMPTR() = BUS().ADDRESS() = DE())++; (MEMPTR() = BUS().ADDRESS() = DE())++;
MEMPTR().high = BUS().DATA() = A(); MEMPTR().high = BUS().DATA() = A();
busWrite(); memoryWrite();
break; break;
case 2: // LD (nn),HL case 2: // LD (nn),HL
BUS().ADDRESS() = fetchWord(); BUS().ADDRESS() = fetchWord();
@@ -1094,7 +1098,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
case 3: // LD (nn),A case 3: // LD (nn),A
(MEMPTR() = BUS().ADDRESS() = fetchWord())++; (MEMPTR() = BUS().ADDRESS() = fetchWord())++;
MEMPTR().high = BUS().DATA() = A(); MEMPTR().high = BUS().DATA() = A();
busWrite(); memoryWrite();
break; break;
default: default:
UNREACHABLE; UNREACHABLE;
@@ -1104,11 +1108,11 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
switch (p) { switch (p) {
case 0: // LD A,(BC) case 0: // LD A,(BC)
(MEMPTR() = BUS().ADDRESS() = BC())++; (MEMPTR() = BUS().ADDRESS() = BC())++;
A() = busRead(); A() = memoryRead();
break; break;
case 1: // LD A,(DE) case 1: // LD A,(DE)
(MEMPTR() = BUS().ADDRESS() = DE())++; (MEMPTR() = BUS().ADDRESS() = DE())++;
A() = busRead(); A() = memoryRead();
break; break;
case 2: // LD HL,(nn) case 2: // LD HL,(nn)
BUS().ADDRESS() = fetchWord(); BUS().ADDRESS() = fetchWord();
@@ -1116,7 +1120,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
break; break;
case 3: // LD A,(nn) case 3: // LD A,(nn)
(MEMPTR() = BUS().ADDRESS() = fetchWord())++; (MEMPTR() = BUS().ADDRESS() = fetchWord())++;
A() = busRead(); A() = memoryRead();
break; break;
default: default:
UNREACHABLE; UNREACHABLE;
@@ -1329,16 +1333,16 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
m_prefixCB = true; m_prefixCB = true;
if (m_displaced) { if (m_displaced) {
fetchDisplacement(); fetchDisplacement();
execute(fetchByte()); IntelProcessor::execute(fetchByte());
} else { } else {
execute(fetchInitialOpCode()); IntelProcessor::execute(fetchInitialOpCode());
} }
break; break;
case 2: // OUT (n),A case 2: // OUT (n),A
writePort(fetchByte()); portWrite(fetchByte());
break; break;
case 3: // IN A,(n) case 3: // IN A,(n)
A() = readPort(fetchByte()); A() = portRead(fetchByte());
break; break;
case 4: // EX (SP),HL case 4: // EX (SP),HL
xhtl(HL2()); xhtl(HL2());
@@ -1371,15 +1375,15 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
break; break;
case 1: // DD prefix case 1: // DD prefix
m_displaced = m_prefixDD = true; m_displaced = m_prefixDD = true;
execute(fetchInitialOpCode()); IntelProcessor::execute(fetchInitialOpCode());
break; break;
case 2: // ED prefix case 2: // ED prefix
m_prefixED = true; m_prefixED = true;
execute(fetchInitialOpCode()); IntelProcessor::execute(fetchInitialOpCode());
break; break;
case 3: // FD prefix case 3: // FD prefix
m_displaced = m_prefixFD = true; m_displaced = m_prefixFD = true;
execute(fetchInitialOpCode()); IntelProcessor::execute(fetchInitialOpCode());
break; break;
default: default:
UNREACHABLE; UNREACHABLE;

View File

@@ -32,7 +32,7 @@ private:
const Configuration& m_configuration; const Configuration& m_configuration;
EightBit::Ram m_ram = 0x10000; EightBit::Ram m_ram = 0x10000;
EightBit::InputOutput m_ports; EightBit::InputOutput m_ports;
EightBit::Z80 m_cpu = { *this, m_ports }; EightBit::Z80 m_cpu = *this;
EightBit::Disassembler m_disassembler = *this; EightBit::Disassembler m_disassembler = *this;
EightBit::Profiler m_profiler = { m_cpu, m_disassembler }; EightBit::Profiler m_profiler = { m_cpu, m_disassembler };
int m_warmstartCount = 0; int m_warmstartCount = 0;

View File

@@ -27,11 +27,11 @@ namespace EightBit {
[[nodiscard]] auto& DATA() noexcept { return m_data; } [[nodiscard]] auto& DATA() noexcept { return m_data; }
[[nodiscard]] auto peek() { return reference(); } [[nodiscard]] auto peek() { return reference(); }
[[nodiscard]] auto peek(const uint16_t address) { return reference(address); } [[nodiscard]] virtual uint8_t peek(const uint16_t address) { return reference(address); }
[[nodiscard]] auto peek(const register16_t address) { return reference(address.word); } [[nodiscard]] auto peek(const register16_t address) { return peek(address.word); }
void poke(const uint8_t value) { reference() = value; } void poke(const uint8_t value) { reference() = value; }
void poke(const uint16_t address, const uint8_t value) { reference(address) = value; } virtual void poke(const uint16_t address, const uint8_t value) { reference(address) = value; }
void poke(const register16_t address, const uint8_t value) { reference(address.word) = value; } void poke(const register16_t address, const uint8_t value) { poke(address.word, value); }
[[nodiscard]] uint8_t read(); [[nodiscard]] uint8_t read();
template<class T> [[nodiscard]] auto read(const T address) { template<class T> [[nodiscard]] auto read(const T address) {

View File

@@ -4,36 +4,51 @@
#include <array> #include <array>
#include "Signal.h" #include "Signal.h"
#include "Memory.h"
#include "Ram.h"
namespace EightBit { namespace EightBit {
class InputOutput final { class InputOutput final : public Memory {
public: public:
enum class AccessType { Unknown, Reading, Writing };
InputOutput() = default; InputOutput() = default;
[[nodiscard]] auto read(const uint8_t port) { return readInputPort(port); } [[nodiscard]] size_t size() const override;
void write(const uint8_t port, const uint8_t value) { writeOutputPort(port, value); } [[nodiscard]] uint8_t peek(uint16_t address) const override;
[[nodiscard]] uint8_t readInputPort(uint8_t port); [[nodiscard]] uint8_t& reference(uint16_t address) override;
void writeInputPort(const uint8_t port, const uint8_t value) noexcept { m_input[port] = value; }
[[nodiscard]] auto readOutputPort(const uint8_t port) noexcept { return m_output[port]; } int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
void writeOutputPort(uint8_t port, uint8_t value); int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
Signal<uint8_t> ReadingPort; AccessType getAccessType() const noexcept { return m_access; }
Signal<uint8_t> ReadPort; void setAccessType(AccessType value) noexcept { m_access = value; }
Signal<uint8_t> WritingPort; auto readPort(uint8_t port, AccessType access) {
Signal<uint8_t> WrittenPort; setAccessType(access);
return reference(port);
}
auto readInputPort(uint8_t port) { return readPort(port, AccessType::Reading); }
auto readOutputPort(uint8_t port) { return readPort(port, AccessType::Writing); }
void writePort(uint8_t port, uint8_t value, AccessType access) {
setAccessType(access);
reference(port) = value;
}
auto writeInputPort(uint8_t port, uint8_t value) { return writePort(port, value, AccessType::Reading); }
auto writeOutputPort(uint8_t port, uint8_t value) { return writePort(port, value, AccessType::Writing); }
protected: protected:
void OnReadingPort(uint8_t port); void poke(uint16_t address, uint8_t value) override;
void OnReadPort(uint8_t port);
void OnWritingPort(uint8_t port);
void OnWrittenPort(uint8_t port);
private: private:
std::array<uint8_t, 0x100> m_input = { 0 }; Ram m_input = 0x100;
std::array<uint8_t, 0x100> m_output = { 0 }; Ram m_output = 0x100;
AccessType m_access = AccessType::Unknown;
}; };
} }

View File

@@ -161,7 +161,7 @@ namespace EightBit {
auto jrConditional(const int condition) { auto jrConditional(const int condition) {
const auto offsetAddress = PC()++; const auto offsetAddress = PC()++;
if (condition) { if (condition) {
const auto offset = busRead(offsetAddress); const auto offset = memoryRead(offsetAddress);
jr(offset); jr(offset);
} }
return condition; return condition;

View File

@@ -8,7 +8,7 @@
namespace EightBit { namespace EightBit {
// Memory is: // Memory is:
// *) Definitely has a size // *) Definitely has a size
// *) Definitely 'peek'able (although you might not like the answer you get!) // *) Probably 'peek'able (although you might not like the answer you get!)
// *) Probably 'load'able (i.e. able to be externally initialised) // *) Probably 'load'able (i.e. able to be externally initialised)
// *) At the implementation level, probably 'poke'able (although may not be exposed to users) // *) At the implementation level, probably 'poke'able (although may not be exposed to users)
// *) Possibly 'reference'able (Very likely if you've exposed 'poke') // *) Possibly 'reference'able (Very likely if you've exposed 'poke')

View File

@@ -41,23 +41,25 @@ namespace EightBit {
virtual void handleRESET(); virtual void handleRESET();
virtual void handleINT(); virtual void handleINT();
void busWrite(register16_t address, uint8_t data); void memoryWrite(register16_t address, uint8_t data);
void busWrite(uint8_t data); void memoryWrite(uint8_t data);
virtual void memoryWrite();
virtual void busWrite(); virtual void busWrite();
uint8_t busRead(register16_t address); uint8_t memoryRead(register16_t address);
virtual uint8_t memoryRead();
virtual uint8_t busRead(); virtual uint8_t busRead();
auto getBytePaged(const uint8_t page, const uint8_t offset) { auto getBytePaged(const uint8_t page, const uint8_t offset) {
return busRead(register16_t(offset, page)); return memoryRead(register16_t(offset, page));
} }
void setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) { void setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) {
busWrite(register16_t(offset, page), value); memoryWrite(register16_t(offset, page), value);
} }
auto fetchByte() { auto fetchByte() {
return busRead(PC()++); return memoryRead(PC()++);
} }
[[nodiscard]] virtual register16_t getWord() = 0; [[nodiscard]] virtual register16_t getWord() = 0;

View File

@@ -5,29 +5,29 @@ EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory)
: Processor(memory) {} : Processor(memory) {}
EightBit::register16_t EightBit::BigEndianProcessor::getWord() { EightBit::register16_t EightBit::BigEndianProcessor::getWord() {
const auto high = busRead(); const auto high = memoryRead();
++BUS().ADDRESS(); ++BUS().ADDRESS();
const auto low = busRead(); const auto low = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::BigEndianProcessor::setWord(const register16_t value) { void EightBit::BigEndianProcessor::setWord(const register16_t value) {
busWrite(value.high); memoryWrite(value.high);
++BUS().ADDRESS(); ++BUS().ADDRESS();
busWrite(value.low); memoryWrite(value.low);
} }
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) { EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
const auto high = getBytePaged(page, offset); const auto high = getBytePaged(page, offset);
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
const auto low = busRead(); const auto low = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) { void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
setBytePaged(page, offset, value.high); setBytePaged(page, offset, value.high);
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
busWrite(value.low); memoryWrite(value.low);
} }
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() { EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() {

View File

@@ -1,31 +1,43 @@
#include "stdafx.h" #include "stdafx.h"
#include "InputOutput.h" #include "InputOutput.h"
uint8_t EightBit::InputOutput::readInputPort(const uint8_t port) { #include <stdexcept>
OnReadingPort(port);
const auto value = m_input[port]; #include "Register.h"
OnReadPort(port);
return value; size_t EightBit::InputOutput::size() const {
return 0x100;
} }
void EightBit::InputOutput::writeOutputPort(const uint8_t port, const uint8_t value) { uint8_t EightBit::InputOutput::peek(uint16_t) const {
OnWritingPort(port); throw std::logic_error("Peek operation not allowed.");
m_output[port] = value;
OnWrittenPort(port);
} }
void EightBit::InputOutput::OnReadingPort(uint8_t port) { uint8_t& EightBit::InputOutput::reference(uint16_t address) {
ReadingPort.fire(port); const auto port = register16_t(address).low;
switch (getAccessType()) {
case AccessType::Reading:
return m_input.reference(port);
case AccessType::Writing:
return m_output.reference(port);
case AccessType::Unknown:
default:
throw std::logic_error("Unknown I/O access type.");
}
} }
void EightBit::InputOutput::OnReadPort(uint8_t port) { int EightBit::InputOutput::load(std::ifstream&, int, int, int) {
ReadPort.fire(port); throw std::logic_error("load operation not allowed.");
} }
void EightBit::InputOutput::OnWritingPort(uint8_t port) { int EightBit::InputOutput::load(const std::string&, int, int, int) {
WritingPort.fire(port); throw std::logic_error("load operation not allowed.");
} }
void EightBit::InputOutput::OnWrittenPort(uint8_t port) { int EightBit::InputOutput::load(const std::vector<uint8_t>&, int, int, int) {
WrittenPort.fire(port); throw std::logic_error("load operation not allowed.");
}
void EightBit::InputOutput::poke(uint16_t, uint8_t) {
throw std::logic_error("Poke operation not allowed.");
} }

View File

@@ -23,11 +23,11 @@ void EightBit::IntelProcessor::handleRESET() {
} }
void EightBit::IntelProcessor::push(const uint8_t value) { void EightBit::IntelProcessor::push(const uint8_t value) {
busWrite(--SP(), value); memoryWrite(--SP(), value);
} }
uint8_t EightBit::IntelProcessor::pop() { uint8_t EightBit::IntelProcessor::pop() {
return busRead(SP()++); return memoryRead(SP()++);
} }
EightBit::register16_t EightBit::IntelProcessor::getWord() { EightBit::register16_t EightBit::IntelProcessor::getWord() {

View File

@@ -5,29 +5,29 @@ EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory)
: Processor(memory) {} : Processor(memory) {}
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() { EightBit::register16_t EightBit::LittleEndianProcessor::getWord() {
const auto low = busRead(); const auto low = memoryRead();
++BUS().ADDRESS(); ++BUS().ADDRESS();
const auto high = busRead(); const auto high = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::LittleEndianProcessor::setWord(const register16_t value) { void EightBit::LittleEndianProcessor::setWord(const register16_t value) {
busWrite(value.low); memoryWrite(value.low);
++BUS().ADDRESS(); ++BUS().ADDRESS();
busWrite(value.high); memoryWrite(value.high);
} }
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) { EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
const auto low = getBytePaged(page, offset); const auto low = getBytePaged(page, offset);
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
const auto high = busRead(); const auto high = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) { void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
setBytePaged(page, offset, value.low); setBytePaged(page, offset, value.low);
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
busWrite(value.high); memoryWrite(value.high);
} }
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() { EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() {

View File

@@ -16,13 +16,17 @@ void EightBit::Processor::handleINT() {
raiseINT(); raiseINT();
} }
void EightBit::Processor::busWrite(const register16_t address, const uint8_t data) { void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
busWrite(data); memoryWrite(data);
} }
void EightBit::Processor::busWrite(const uint8_t data) { void EightBit::Processor::memoryWrite(const uint8_t data) {
BUS().DATA() = data; BUS().DATA() = data;
memoryWrite();
}
void EightBit::Processor::memoryWrite() {
busWrite(); busWrite();
} }
@@ -30,8 +34,12 @@ void EightBit::Processor::busWrite() {
BUS().write(); BUS().write();
} }
uint8_t EightBit::Processor::busRead(const register16_t address) { uint8_t EightBit::Processor::memoryRead(const register16_t address) {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
return memoryRead();
}
uint8_t EightBit::Processor::memoryRead() {
return busRead(); return busRead();
} }