mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-22 09:30:32 +00:00
Ensure the Z80 unit tests run successfully to completion.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
c472d70c5c
commit
cae34d61d1
@ -4,7 +4,7 @@
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <Register.h>
|
||||
|
||||
namespace Fuse {
|
||||
class RegisterState {
|
||||
|
@ -5,11 +5,10 @@
|
||||
Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expected)
|
||||
: m_test(test),
|
||||
m_expected(expected),
|
||||
m_memory(0xffff),
|
||||
m_cpu(m_memory, m_ports),
|
||||
m_ram(0x10000),
|
||||
m_cpu(*this, m_ports),
|
||||
m_failed(false),
|
||||
m_unimplemented(false) {
|
||||
m_memory.clear();
|
||||
m_cpu.initialise();
|
||||
}
|
||||
|
||||
@ -57,7 +56,7 @@ void Fuse::TestRunner::initialiseMemory() {
|
||||
auto address = memoryDatum.address;
|
||||
auto bytes = memoryDatum.bytes;
|
||||
for (int i = 0; i < bytes.size(); ++i)
|
||||
m_memory.poke(address + i, bytes[i]);
|
||||
poke(address + i, bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +303,7 @@ void Fuse::TestRunner::checkMemory() {
|
||||
for (int i = 0; i < bytes.size(); ++i) {
|
||||
auto expected = bytes[i];
|
||||
uint16_t address = memoryDatum.address + i;
|
||||
auto actual = m_cpu.getMemory().peek(address);
|
||||
auto actual = peek(address);
|
||||
if (expected != actual) {
|
||||
m_failed = true;
|
||||
if (first) {
|
||||
|
@ -3,12 +3,13 @@
|
||||
#include "FuseTest.h"
|
||||
#include "FuseExpectedTestResult.h"
|
||||
|
||||
#include "Memory.h"
|
||||
#include "InputOutput.h"
|
||||
#include "Z80.h"
|
||||
#include <Ram.h>
|
||||
#include <Bus.h>
|
||||
#include <InputOutput.h>
|
||||
#include <Z80.h>
|
||||
|
||||
namespace Fuse {
|
||||
class TestRunner {
|
||||
class TestRunner : public EightBit::Bus {
|
||||
private:
|
||||
const Test& m_test;
|
||||
const ExpectedTestResult& m_expected;
|
||||
@ -16,7 +17,7 @@ namespace Fuse {
|
||||
bool m_failed;
|
||||
bool m_unimplemented;
|
||||
|
||||
EightBit::Memory m_memory;
|
||||
EightBit::Ram m_ram;
|
||||
EightBit::InputOutput m_ports;
|
||||
EightBit::Z80 m_cpu;
|
||||
|
||||
@ -34,6 +35,12 @@ namespace Fuse {
|
||||
const std::string& lowDescription,
|
||||
EightBit::register16_t actual, EightBit::register16_t expected) const;
|
||||
|
||||
protected:
|
||||
virtual uint8_t& reference(uint16_t address, bool& rom) {
|
||||
rom = false;
|
||||
return m_ram.reference(address);
|
||||
}
|
||||
|
||||
public:
|
||||
TestRunner(const Test& test, const ExpectedTestResult& expected);
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace EightBit {
|
||||
CF = Bit0,
|
||||
};
|
||||
|
||||
Z80(Memory& memory, InputOutput& ports);
|
||||
Z80(Bus& bus, InputOutput& ports);
|
||||
|
||||
Signal<Z80> ExecutingInstruction;
|
||||
|
||||
|
@ -178,8 +178,8 @@ std::string EightBit::Disassembler::disassemble(Z80& cpu) {
|
||||
|
||||
void EightBit::Disassembler::disassemble(std::ostringstream& output, Z80& cpu, uint16_t pc) {
|
||||
|
||||
auto& memory = cpu.getMemory();
|
||||
auto opcode = memory.peek(pc);
|
||||
auto& bus = cpu.BUS();
|
||||
auto opcode = bus.peek(pc);
|
||||
|
||||
const auto& decoded = cpu.getDecodedOpcode(opcode);
|
||||
|
||||
@ -190,11 +190,11 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, Z80& cpu, u
|
||||
auto p = decoded.p;
|
||||
auto q = decoded.q;
|
||||
|
||||
auto immediate = memory.peek(pc + 1);
|
||||
auto absolute = memory.peekWord(pc + 1);
|
||||
auto immediate = bus.peek(pc + 1);
|
||||
auto absolute = bus.peekWord(pc + 1);
|
||||
auto displacement = (int8_t)immediate;
|
||||
auto relative = pc + displacement + 2;
|
||||
auto indexedImmediate = memory.peek(pc + 1);
|
||||
auto indexedImmediate = bus.peek(pc + 1);
|
||||
|
||||
auto dumpCount = 0;
|
||||
|
||||
@ -219,7 +219,7 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, Z80& cpu, u
|
||||
x, y, z, p, q);
|
||||
|
||||
for (int i = 0; i < dumpCount; ++i)
|
||||
output << hex(memory.peek(pc + i + 1));
|
||||
output << hex(bus.peek(pc + i + 1));
|
||||
|
||||
auto outputFormatSpecification = !m_prefixDD;
|
||||
if (m_prefixDD) {
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#pragma region Reset and initialisation
|
||||
|
||||
EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
|
||||
: IntelProcessor(memory),
|
||||
EightBit::Z80::Z80(Bus& bus, InputOutput& ports)
|
||||
: IntelProcessor(bus),
|
||||
m_ports(ports),
|
||||
m_registerSet(0),
|
||||
m_accumulatorFlagsSet(0),
|
||||
@ -509,7 +509,7 @@ void EightBit::Z80::xhtl(register16_t& operand) {
|
||||
MEMPTR().low = getByte(SP());
|
||||
setByte(operand.low);
|
||||
operand.low = MEMPTR().low;
|
||||
m_memory.ADDRESS().word++;
|
||||
BUS().ADDRESS().word++;
|
||||
MEMPTR().high = getByte();
|
||||
setByte(operand.high);
|
||||
operand.high = MEMPTR().high;
|
||||
@ -615,20 +615,20 @@ bool EightBit::Z80::lddr(uint8_t a, uint8_t& f) {
|
||||
#pragma region Block input instructions
|
||||
|
||||
void EightBit::Z80::ini(uint8_t& f) {
|
||||
MEMPTR() = m_memory.ADDRESS() = BC();
|
||||
MEMPTR() = BUS().ADDRESS() = BC();
|
||||
MEMPTR().word++;
|
||||
readPort();
|
||||
auto value = m_memory.DATA();
|
||||
auto value = BUS().DATA();
|
||||
setByte(HL().word++, value);
|
||||
decrement(f, B());
|
||||
setFlag(f, NF);
|
||||
}
|
||||
|
||||
void EightBit::Z80::ind(uint8_t& f) {
|
||||
MEMPTR() = m_memory.ADDRESS() = BC();
|
||||
MEMPTR() = BUS().ADDRESS() = BC();
|
||||
MEMPTR().word--;
|
||||
readPort();
|
||||
auto value = m_memory.DATA();
|
||||
auto value = BUS().DATA();
|
||||
setByte(HL().word--, value);
|
||||
decrement(f, B());
|
||||
setFlag(f, NF);
|
||||
@ -650,7 +650,7 @@ bool EightBit::Z80::indr(uint8_t& f) {
|
||||
|
||||
void EightBit::Z80::blockOut(uint8_t& f) {
|
||||
auto value = getByte();
|
||||
m_memory.ADDRESS() = BC();
|
||||
BUS().ADDRESS() = BC();
|
||||
writePort();
|
||||
decrement(f, B());
|
||||
setFlag(f, NF, value & Bit7);
|
||||
@ -659,13 +659,13 @@ void EightBit::Z80::blockOut(uint8_t& f) {
|
||||
}
|
||||
|
||||
void EightBit::Z80::outi(uint8_t& f) {
|
||||
m_memory.ADDRESS().word = HL().word++;
|
||||
BUS().ADDRESS().word = HL().word++;
|
||||
blockOut(f);
|
||||
MEMPTR().word = BC().word + 1;
|
||||
}
|
||||
|
||||
void EightBit::Z80::outd(uint8_t& f) {
|
||||
m_memory.ADDRESS().word = HL().word--;
|
||||
BUS().ADDRESS().word = HL().word--;
|
||||
blockOut(f);
|
||||
MEMPTR().word = BC().word - 1;
|
||||
}
|
||||
@ -711,29 +711,29 @@ void EightBit::Z80::rld(uint8_t& a, uint8_t& f) {
|
||||
#pragma region I/O instructions
|
||||
|
||||
void EightBit::Z80::writePort(uint8_t port, uint8_t data) {
|
||||
m_memory.ADDRESS().low = port;
|
||||
m_memory.ADDRESS().high = data;
|
||||
MEMPTR() = m_memory.ADDRESS();
|
||||
m_memory.placeDATA(data);
|
||||
BUS().ADDRESS().low = port;
|
||||
BUS().ADDRESS().high = data;
|
||||
MEMPTR() = BUS().ADDRESS();
|
||||
BUS().placeDATA(data);
|
||||
writePort();
|
||||
MEMPTR().low++;
|
||||
}
|
||||
|
||||
void EightBit::Z80::writePort() {
|
||||
m_ports.write(m_memory.ADDRESS().low, m_memory.DATA());
|
||||
m_ports.write(BUS().ADDRESS().low, BUS().DATA());
|
||||
}
|
||||
|
||||
void EightBit::Z80::readPort(uint8_t port, uint8_t& a) {
|
||||
m_memory.ADDRESS().low = port;
|
||||
m_memory.ADDRESS().high = a;
|
||||
MEMPTR() = m_memory.ADDRESS();
|
||||
BUS().ADDRESS().low = port;
|
||||
BUS().ADDRESS().high = a;
|
||||
MEMPTR() = BUS().ADDRESS();
|
||||
readPort();
|
||||
a = m_memory.DATA();
|
||||
a = BUS().DATA();
|
||||
MEMPTR().low++;
|
||||
}
|
||||
|
||||
void EightBit::Z80::readPort() {
|
||||
m_memory.placeDATA(m_ports.read(m_memory.ADDRESS().low));
|
||||
BUS().placeDATA(m_ports.read(BUS().ADDRESS().low));
|
||||
}
|
||||
|
||||
#pragma endregion I/O instructions
|
||||
@ -893,22 +893,22 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
|
||||
case 1:
|
||||
switch (z) {
|
||||
case 0: // Input from port with 16-bit address
|
||||
MEMPTR() = m_memory.ADDRESS() = BC();
|
||||
MEMPTR() = BUS().ADDRESS() = BC();
|
||||
MEMPTR().word++;
|
||||
readPort();
|
||||
if (y != 6) // IN r[y],(C)
|
||||
R(y, a, m_memory.DATA());
|
||||
adjustSZPXY<Z80>(f, m_memory.DATA());
|
||||
R(y, a, BUS().DATA());
|
||||
adjustSZPXY<Z80>(f, BUS().DATA());
|
||||
clearFlag(f, NF | HC);
|
||||
cycles += 12;
|
||||
break;
|
||||
case 1: // Output to port with 16-bit address
|
||||
MEMPTR() = m_memory.ADDRESS() = BC();
|
||||
MEMPTR() = BUS().ADDRESS() = BC();
|
||||
MEMPTR().word++;
|
||||
if (y == 6) // OUT (C),0
|
||||
m_memory.placeDATA(0);
|
||||
BUS().placeDATA(0);
|
||||
else // OUT (C),r[y]
|
||||
m_memory.placeDATA(R(y, a));
|
||||
BUS().placeDATA(R(y, a));
|
||||
writePort();
|
||||
cycles += 12;
|
||||
break;
|
||||
|
@ -4,23 +4,22 @@
|
||||
|
||||
Board::Board(const Configuration& configuration)
|
||||
: m_configuration(configuration),
|
||||
m_memory(0x3fff),
|
||||
m_cpu(EightBit::Z80(m_memory, m_ports)),
|
||||
m_ram(0x10000),
|
||||
m_cpu(EightBit::Z80(*this, m_ports)),
|
||||
m_profiler(m_cpu, m_disassembler) {
|
||||
}
|
||||
|
||||
void Board::initialise() {
|
||||
|
||||
m_memory.clear();
|
||||
auto romDirectory = m_configuration.getRomDirectory();
|
||||
|
||||
//m_memory.loadRam(romDirectory + "/prelim.com", 0x100); // Bartholomew preliminary
|
||||
//m_memory.loadRam(romDirectory + "/zexdoc.com", 0x100); // Cringle/Bartholomew
|
||||
m_memory.loadRam(romDirectory + "/zexall.com", 0x100); // Cringle/Bartholomew
|
||||
//m_memory.loadRam(romDirectory + "/CPUTEST.COM", 0x100); // SuperSoft diagnostics
|
||||
//m_memory.loadRam(romDirectory + "/TEST.COM", 0x100); // Microcosm
|
||||
//m_ram.load(romDirectory + "/prelim.com", 0x100); // Bartholomew preliminary
|
||||
//m_ram.load(romDirectory + "/zexdoc.com", 0x100); // Cringle/Bartholomew
|
||||
m_ram.load(romDirectory + "/zexall.com", 0x100); // Cringle/Bartholomew
|
||||
//m_ram.load(romDirectory + "/CPUTEST.COM", 0x100); // SuperSoft diagnostics
|
||||
//m_ram.load(romDirectory + "/TEST.COM", 0x100); // Microcosm
|
||||
|
||||
m_memory.poke(5, 0xc9); // ret
|
||||
poke(5, 0xc9); // ret
|
||||
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Cpm, this, std::placeholders::_1));
|
||||
|
||||
if (m_configuration.isProfileMode()) {
|
||||
@ -61,8 +60,8 @@ void Board::bdos() {
|
||||
break;
|
||||
}
|
||||
case 0x9:
|
||||
for (uint16_t i = m_cpu.DE().word; m_memory.peek(i) != '$'; ++i) {
|
||||
std::cout << m_memory.peek(i);
|
||||
for (uint16_t i = m_cpu.DE().word; peek(i) != '$'; ++i) {
|
||||
std::cout << peek(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -73,7 +72,7 @@ void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpu) {
|
||||
const auto pc = m_cpu.PC();
|
||||
|
||||
m_profiler.addAddress(pc.word);
|
||||
m_profiler.addInstruction(m_memory.peek(pc.word));
|
||||
m_profiler.addInstruction(peek(pc.word));
|
||||
}
|
||||
|
||||
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Z80& cpu) {
|
||||
|
@ -2,26 +2,33 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Memory.h"
|
||||
#include "InputOutput.h"
|
||||
#include "Configuration.h"
|
||||
#include "Profiler.h"
|
||||
#include "EventArgs.h"
|
||||
#include "Disassembler.h"
|
||||
#include "Z80.h"
|
||||
#include <Ram.h>
|
||||
#include <Bus.h>
|
||||
#include <InputOutput.h>
|
||||
#include <Profiler.h>
|
||||
#include <EventArgs.h>
|
||||
#include <Disassembler.h>
|
||||
#include <Z80.h>
|
||||
|
||||
class Board {
|
||||
#include "Configuration.h"
|
||||
|
||||
class Board : public EightBit::Bus {
|
||||
public:
|
||||
Board(const Configuration& configuration);
|
||||
|
||||
EightBit::Memory& Memory() { return m_memory; }
|
||||
EightBit::Z80& CPU() { return m_cpu; }
|
||||
|
||||
void initialise();
|
||||
|
||||
protected:
|
||||
virtual uint8_t& reference(uint16_t address, bool& rom) {
|
||||
rom = false;
|
||||
return m_ram.reference(address);
|
||||
}
|
||||
|
||||
private:
|
||||
const Configuration& m_configuration;
|
||||
EightBit::Memory m_memory;
|
||||
EightBit::Ram m_ram;
|
||||
EightBit::InputOutput m_ports;
|
||||
EightBit::Z80 m_cpu;
|
||||
EightBit::Disassembler m_disassembler;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Memory.h"
|
||||
#include <Register.h>
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user