mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-02-01 00:34:06 +00:00
Add Z80 processor and tests.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
4c6f44c394
commit
211c75d84d
20
EightBit.sln
20
EightBit.sln
@ -9,6 +9,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Intel8080", "Intel8080\src\
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_Intel8080", "Intel8080\test\test_Intel8080.vcxproj", "{391D3B95-D9DA-47E5-9F61-70483F6BB396}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Z80", "Z80\src\Z80.vcxproj", "{01974F81-2750-45AF-B845-2C903A54A334}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_Z80", "Z80\test\test_Z80.vcxproj", "{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -41,6 +45,22 @@ Global
|
||||
{391D3B95-D9DA-47E5-9F61-70483F6BB396}.Release|x64.Build.0 = Release|x64
|
||||
{391D3B95-D9DA-47E5-9F61-70483F6BB396}.Release|x86.ActiveCfg = Release|Win32
|
||||
{391D3B95-D9DA-47E5-9F61-70483F6BB396}.Release|x86.Build.0 = Release|Win32
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Debug|x64.Build.0 = Debug|x64
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Debug|x86.Build.0 = Debug|Win32
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Release|x64.ActiveCfg = Release|x64
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Release|x64.Build.0 = Release|x64
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Release|x86.ActiveCfg = Release|Win32
|
||||
{01974F81-2750-45AF-B845-2C903A54A334}.Release|x86.Build.0 = Release|Win32
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Debug|x64.Build.0 = Debug|x64
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Release|x64.ActiveCfg = Release|x64
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Release|x64.Build.0 = Release|x64
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -158,7 +158,7 @@ namespace EightBit {
|
||||
void jmpConditional(int conditional) {
|
||||
auto destination = fetchWord();
|
||||
if (conditional)
|
||||
pc.word = destination;
|
||||
pc = destination;
|
||||
}
|
||||
|
||||
void callConditional(int condition) {
|
||||
@ -325,9 +325,9 @@ namespace EightBit {
|
||||
m_memory.set(HL().word, data);
|
||||
}
|
||||
|
||||
void lxi_b() { BC().word = fetchWord(); }
|
||||
void lxi_d() { DE().word = fetchWord(); }
|
||||
void lxi_h() { HL().word = fetchWord(); }
|
||||
void lxi_b() { BC() = fetchWord(); }
|
||||
void lxi_d() { DE() = fetchWord(); }
|
||||
void lxi_h() { HL() = fetchWord(); }
|
||||
|
||||
void stax_b() { m_memory.set(BC().word, A()); }
|
||||
void stax_d() { m_memory.set(DE().word, A()); }
|
||||
@ -337,21 +337,21 @@ namespace EightBit {
|
||||
|
||||
void sta() {
|
||||
auto destination = fetchWord();
|
||||
m_memory.set(destination, A());
|
||||
m_memory.set(destination.word, A());
|
||||
}
|
||||
|
||||
void lda() {
|
||||
auto source = fetchWord();
|
||||
A() = m_memory.get(source);
|
||||
A() = m_memory.get(source.word);
|
||||
}
|
||||
|
||||
void shld() {
|
||||
auto destination = fetchWord();
|
||||
setWord(destination, HL());
|
||||
m_memory.setWord(destination.word, HL());
|
||||
}
|
||||
|
||||
void lhld() {
|
||||
HL() = getWord(fetchWord());
|
||||
HL() = m_memory.getWord(fetchWord().word);
|
||||
}
|
||||
|
||||
void xchg() {
|
||||
@ -382,8 +382,8 @@ namespace EightBit {
|
||||
}
|
||||
|
||||
void xhtl() {
|
||||
auto tos = getWord(sp.word);
|
||||
setWord(sp.word, HL());
|
||||
auto tos = m_memory.getWord(sp.word);
|
||||
m_memory.setWord(sp.word, HL());
|
||||
HL() = tos;
|
||||
}
|
||||
|
||||
@ -392,7 +392,7 @@ namespace EightBit {
|
||||
}
|
||||
|
||||
void lxi_sp() {
|
||||
sp.word = fetchWord();
|
||||
sp = fetchWord();
|
||||
}
|
||||
|
||||
void inx_sp() { ++sp.word; }
|
||||
@ -421,7 +421,7 @@ namespace EightBit {
|
||||
// call
|
||||
|
||||
void call() {
|
||||
auto destination = getWord(pc.word);
|
||||
auto destination = m_memory.getWord(pc.word);
|
||||
callAddress(destination.word);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ std::string EightBit::Disassembler::disassemble(Intel8080& cpu) {
|
||||
output << hex(memory.peek(pc.word + 1));
|
||||
break;
|
||||
case Intel8080::Absolute:
|
||||
output << hex(cpu.getWord(pc.word + 1).word);
|
||||
output << hex(memory.peekWord(pc.word + 1));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -3,63 +3,66 @@
|
||||
#include <string>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
class Z80;
|
||||
namespace EightBit {
|
||||
|
||||
class Disassembler {
|
||||
public:
|
||||
Disassembler();
|
||||
class Z80;
|
||||
|
||||
static std::string state(Z80& cpu);
|
||||
std::string disassemble(const Z80& cpu);
|
||||
class Disassembler {
|
||||
public:
|
||||
Disassembler();
|
||||
|
||||
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
||||
static std::string flags(uint8_t value);
|
||||
static std::string hex(uint8_t value);
|
||||
static std::string hex(uint16_t value);
|
||||
static std::string binary(uint8_t value);
|
||||
static std::string decimal(uint8_t value);
|
||||
static std::string state(Z80& cpu);
|
||||
std::string disassemble(const Z80& cpu);
|
||||
|
||||
static std::string invalid(uint8_t value);
|
||||
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
||||
static std::string flags(uint8_t value);
|
||||
static std::string hex(uint8_t value);
|
||||
static std::string hex(uint16_t value);
|
||||
static std::string binary(uint8_t value);
|
||||
static std::string decimal(uint8_t value);
|
||||
|
||||
private:
|
||||
mutable boost::format m_formatter;
|
||||
bool m_prefixCB;
|
||||
bool m_prefixDD;
|
||||
bool m_prefixED;
|
||||
bool m_prefixFD;
|
||||
static std::string invalid(uint8_t value);
|
||||
|
||||
void disassemble(std::ostringstream& output, const Z80& cpu, uint16_t pc);
|
||||
private:
|
||||
mutable boost::format m_formatter;
|
||||
bool m_prefixCB;
|
||||
bool m_prefixDD;
|
||||
bool m_prefixED;
|
||||
bool m_prefixFD;
|
||||
|
||||
void disassembleCB(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
void disassemble(std::ostringstream& output, const Z80& cpu, uint16_t pc);
|
||||
|
||||
void disassembleED(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
void disassembleCB(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
|
||||
void disassembleOther(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
void disassembleED(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
|
||||
std::string RP(int rp) const;
|
||||
std::string RP2(int rp) const;
|
||||
std::string R(int r) const;
|
||||
static std::string cc(int flag);
|
||||
static std::string alu(int which);
|
||||
};
|
||||
void disassembleOther(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
|
||||
std::string RP(int rp) const;
|
||||
std::string RP2(int rp) const;
|
||||
std::string R(int r) const;
|
||||
static std::string cc(int flag);
|
||||
static std::string alu(int which);
|
||||
};
|
||||
}
|
@ -4,33 +4,35 @@
|
||||
#include "Signal.h"
|
||||
#include "PortEventArgs.h"
|
||||
|
||||
class InputOutput {
|
||||
public:
|
||||
InputOutput();
|
||||
namespace EightBit {
|
||||
class InputOutput {
|
||||
public:
|
||||
InputOutput();
|
||||
|
||||
uint8_t read(uint8_t port) { return readInputPort(port); }
|
||||
void write(uint8_t port, uint8_t value) { return writeOutputPort(port, value); }
|
||||
uint8_t read(uint8_t port) { return readInputPort(port); }
|
||||
void write(uint8_t port, uint8_t value) { return writeOutputPort(port, value); }
|
||||
|
||||
uint8_t readInputPort(uint8_t port);
|
||||
void writeInputPort(uint8_t port, uint8_t value) { input[port] = value; }
|
||||
uint8_t readInputPort(uint8_t port);
|
||||
void writeInputPort(uint8_t port, uint8_t value) { input[port] = value; }
|
||||
|
||||
uint8_t readOutputPort(uint8_t port) { return output[port]; }
|
||||
void writeOutputPort(uint8_t port, uint8_t value);
|
||||
uint8_t readOutputPort(uint8_t port) { return output[port]; }
|
||||
void writeOutputPort(uint8_t port, uint8_t value);
|
||||
|
||||
Signal<PortEventArgs> ReadingPort;
|
||||
Signal<PortEventArgs> ReadPort;
|
||||
Signal<PortEventArgs> ReadingPort;
|
||||
Signal<PortEventArgs> ReadPort;
|
||||
|
||||
Signal<PortEventArgs> WritingPort;
|
||||
Signal<PortEventArgs> WrittenPort;
|
||||
Signal<PortEventArgs> WritingPort;
|
||||
Signal<PortEventArgs> WrittenPort;
|
||||
|
||||
protected:
|
||||
void OnReadingPort(uint8_t port);
|
||||
void OnReadPort(uint8_t port);
|
||||
protected:
|
||||
void OnReadingPort(uint8_t port);
|
||||
void OnReadPort(uint8_t port);
|
||||
|
||||
void OnWritingPort(uint8_t port);
|
||||
void OnWrittenPort(uint8_t port);
|
||||
void OnWritingPort(uint8_t port);
|
||||
void OnWrittenPort(uint8_t port);
|
||||
|
||||
private:
|
||||
std::array<uint8_t, 0x100> input;
|
||||
std::array<uint8_t, 0x100> output;
|
||||
};
|
||||
private:
|
||||
std::array<uint8_t, 0x100> input;
|
||||
std::array<uint8_t, 0x100> output;
|
||||
};
|
||||
}
|
@ -2,15 +2,17 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class PortEventArgs {
|
||||
public:
|
||||
PortEventArgs(uint8_t port)
|
||||
: m_port(port) {}
|
||||
namespace EightBit {
|
||||
class PortEventArgs {
|
||||
public:
|
||||
PortEventArgs(uint8_t port)
|
||||
: m_port(port) {}
|
||||
|
||||
uint8_t getPort() const {
|
||||
return m_port;
|
||||
}
|
||||
uint8_t getPort() const {
|
||||
return m_port;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t m_port;
|
||||
};
|
||||
private:
|
||||
uint8_t m_port;
|
||||
};
|
||||
}
|
@ -3,21 +3,22 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
class Profiler {
|
||||
public:
|
||||
Profiler();
|
||||
~Profiler();
|
||||
namespace EightBit {
|
||||
class Profiler {
|
||||
public:
|
||||
Profiler();
|
||||
~Profiler();
|
||||
|
||||
void addInstruction(uint8_t instruction);
|
||||
void addAddress(uint16_t address);
|
||||
void addInstruction(uint8_t instruction);
|
||||
void addAddress(uint16_t address);
|
||||
|
||||
void dump() const;
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
std::array<uint64_t, 0x100> m_instructions;
|
||||
std::array<uint64_t, 0x10000> m_addresses;
|
||||
|
||||
void dumpInstructionProfiles() const;
|
||||
void dumpAddressProfiles() const;
|
||||
};
|
||||
private:
|
||||
std::array<uint64_t, 0x100> m_instructions;
|
||||
std::array<uint64_t, 0x10000> m_addresses;
|
||||
|
||||
void dumpInstructionProfiles() const;
|
||||
void dumpAddressProfiles() const;
|
||||
};
|
||||
}
|
705
Z80/inc/Z80.h
705
Z80/inc/Z80.h
@ -1,449 +1,456 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "Processor.h"
|
||||
#include "InputOutput.h"
|
||||
|
||||
class Z80 : public Processor {
|
||||
public:
|
||||
enum StatusBits {
|
||||
SF = Bit7,
|
||||
ZF = Bit6,
|
||||
YF = Bit5,
|
||||
HC = Bit4,
|
||||
XF = Bit3,
|
||||
PF = Bit2,
|
||||
VF = Bit2,
|
||||
NF = Bit1,
|
||||
CF = Bit0,
|
||||
};
|
||||
namespace EightBit {
|
||||
class Z80 : public Processor {
|
||||
public:
|
||||
enum StatusBits {
|
||||
SF = Bit7,
|
||||
ZF = Bit6,
|
||||
YF = Bit5,
|
||||
HC = Bit4,
|
||||
XF = Bit3,
|
||||
PF = Bit2,
|
||||
VF = Bit2,
|
||||
NF = Bit1,
|
||||
CF = Bit0,
|
||||
};
|
||||
|
||||
Z80(Memory& memory, InputOutput& ports);
|
||||
Z80(Memory& memory, InputOutput& ports);
|
||||
|
||||
Signal<Z80> ExecutingInstruction;
|
||||
Signal<Z80> ExecutingInstruction;
|
||||
|
||||
void disableInterrupts();
|
||||
void enableInterrupts();
|
||||
void disableInterrupts();
|
||||
void enableInterrupts();
|
||||
|
||||
int interruptMaskable(uint8_t value) { return interrupt(true, value); }
|
||||
int interruptMaskable() { return interruptMaskable(0); }
|
||||
int interruptNonMaskable() { return interrupt(false, 0); }
|
||||
int interruptMaskable(uint8_t value) { return interrupt(true, value); }
|
||||
int interruptMaskable() { return interruptMaskable(0); }
|
||||
int interruptNonMaskable() { return interrupt(false, 0); }
|
||||
|
||||
int interrupt(bool maskable, uint8_t value);
|
||||
int interrupt(bool maskable, uint8_t value);
|
||||
|
||||
int execute(uint8_t opcode);
|
||||
int step();
|
||||
int execute(uint8_t opcode);
|
||||
int step();
|
||||
|
||||
bool getM1() const { return m1; }
|
||||
bool getM1() const { return m1; }
|
||||
|
||||
// Mutable access to processor!!
|
||||
// Mutable access to processor!!
|
||||
|
||||
register16_t& AF() {
|
||||
return m_accumulatorFlags[m_accumulatorFlagsSet];
|
||||
}
|
||||
register16_t& AF() {
|
||||
return m_accumulatorFlags[m_accumulatorFlagsSet];
|
||||
}
|
||||
|
||||
uint8_t& A() { return AF().high; }
|
||||
uint8_t& F() { return AF().low; }
|
||||
uint8_t& A() { return AF().high; }
|
||||
uint8_t& F() { return AF().low; }
|
||||
|
||||
register16_t& BC() {
|
||||
return m_registers[m_registerSet][BC_IDX];
|
||||
}
|
||||
register16_t& BC() {
|
||||
return m_registers[m_registerSet][BC_IDX];
|
||||
}
|
||||
|
||||
uint8_t& B() { return BC().high; }
|
||||
uint8_t& C() { return BC().low; }
|
||||
uint8_t& B() { return BC().high; }
|
||||
uint8_t& C() { return BC().low; }
|
||||
|
||||
register16_t& DE() {
|
||||
return m_registers[m_registerSet][DE_IDX];
|
||||
}
|
||||
register16_t& DE() {
|
||||
return m_registers[m_registerSet][DE_IDX];
|
||||
}
|
||||
|
||||
uint8_t& D() { return DE().high; }
|
||||
uint8_t& E() { return DE().low; }
|
||||
uint8_t& D() { return DE().high; }
|
||||
uint8_t& E() { return DE().low; }
|
||||
|
||||
register16_t& HL() {
|
||||
return m_registers[m_registerSet][HL_IDX];
|
||||
}
|
||||
register16_t& HL() {
|
||||
return m_registers[m_registerSet][HL_IDX];
|
||||
}
|
||||
|
||||
uint8_t& H() { return HL().high; }
|
||||
uint8_t& L() { return HL().low; }
|
||||
uint8_t& H() { return HL().high; }
|
||||
uint8_t& L() { return HL().low; }
|
||||
|
||||
register16_t& IX() { return m_ix; }
|
||||
uint8_t& IXH() { return IX().high; }
|
||||
uint8_t& IXL() { return IX().low; }
|
||||
register16_t& IX() { return m_ix; }
|
||||
uint8_t& IXH() { return IX().high; }
|
||||
uint8_t& IXL() { return IX().low; }
|
||||
|
||||
register16_t& IY() { return m_iy; }
|
||||
uint8_t& IYH() { return IY().high; }
|
||||
uint8_t& IYL() { return IY().low; }
|
||||
register16_t& IY() { return m_iy; }
|
||||
uint8_t& IYH() { return IY().high; }
|
||||
uint8_t& IYL() { return IY().low; }
|
||||
|
||||
uint8_t& REFRESH() { return m_refresh; }
|
||||
uint8_t& IV() { return iv; }
|
||||
int& IM() { return m_interruptMode; }
|
||||
bool& IFF1() { return m_iff1; }
|
||||
bool& IFF2() { return m_iff2; }
|
||||
uint8_t& REFRESH() { return m_refresh; }
|
||||
uint8_t& IV() { return iv; }
|
||||
int& IM() { return m_interruptMode; }
|
||||
bool& IFF1() { return m_iff1; }
|
||||
bool& IFF2() { return m_iff2; }
|
||||
|
||||
register16_t& MEMPTR() { return m_memptr; }
|
||||
register16_t& MEMPTR() { return m_memptr; }
|
||||
|
||||
bool& M1() { return m1; }
|
||||
bool& M1() { return m1; }
|
||||
|
||||
void exx() {
|
||||
m_registerSet ^= 1;
|
||||
}
|
||||
void exx() {
|
||||
m_registerSet ^= 1;
|
||||
}
|
||||
|
||||
void exxAF() {
|
||||
m_accumulatorFlagsSet = !m_accumulatorFlagsSet;
|
||||
}
|
||||
void exxAF() {
|
||||
m_accumulatorFlagsSet = !m_accumulatorFlagsSet;
|
||||
}
|
||||
|
||||
virtual void reset();
|
||||
virtual void initialise();
|
||||
virtual void reset();
|
||||
virtual void initialise();
|
||||
|
||||
private:
|
||||
enum { BC_IDX, DE_IDX, HL_IDX };
|
||||
private:
|
||||
InputOutput& m_ports;
|
||||
|
||||
std::array<std::array<register16_t, 3>, 2> m_registers;
|
||||
int m_registerSet;
|
||||
enum { BC_IDX, DE_IDX, HL_IDX };
|
||||
|
||||
std::array<register16_t, 2> m_accumulatorFlags;
|
||||
int m_accumulatorFlagsSet;
|
||||
std::array<std::array<register16_t, 3>, 2> m_registers;
|
||||
int m_registerSet;
|
||||
|
||||
register16_t m_ix;
|
||||
register16_t m_iy;
|
||||
std::array<register16_t, 2> m_accumulatorFlags;
|
||||
int m_accumulatorFlagsSet;
|
||||
|
||||
uint8_t m_refresh;
|
||||
uint8_t iv;
|
||||
int m_interruptMode;
|
||||
bool m_iff1;
|
||||
bool m_iff2;
|
||||
register16_t m_ix;
|
||||
register16_t m_iy;
|
||||
|
||||
register16_t m_memptr;
|
||||
uint8_t m_refresh;
|
||||
uint8_t iv;
|
||||
int m_interruptMode;
|
||||
bool m_iff1;
|
||||
bool m_iff2;
|
||||
|
||||
bool m1;
|
||||
register16_t m_memptr;
|
||||
|
||||
bool m_prefixCB;
|
||||
bool m_prefixDD;
|
||||
bool m_prefixED;
|
||||
bool m_prefixFD;
|
||||
bool m1;
|
||||
|
||||
int8_t m_displacement;
|
||||
bool m_prefixCB;
|
||||
bool m_prefixDD;
|
||||
bool m_prefixED;
|
||||
bool m_prefixFD;
|
||||
|
||||
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
|
||||
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
|
||||
int8_t m_displacement;
|
||||
|
||||
int fetchExecute() {
|
||||
M1() = true;
|
||||
return execute(fetchByteExecute());
|
||||
}
|
||||
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
|
||||
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
|
||||
|
||||
uint8_t fetchByteExecute() {
|
||||
if (!getM1())
|
||||
throw std::logic_error("M1 cannot be high");
|
||||
return fetchByte();
|
||||
}
|
||||
int fetchExecute() {
|
||||
M1() = true;
|
||||
return execute(fetchByteExecute());
|
||||
}
|
||||
|
||||
uint8_t fetchByteData() {
|
||||
if (getM1())
|
||||
throw std::logic_error("M1 cannot be low");
|
||||
return fetchByte();
|
||||
}
|
||||
uint8_t fetchByteExecute() {
|
||||
if (!getM1())
|
||||
throw std::logic_error("M1 cannot be high");
|
||||
return fetchByte();
|
||||
}
|
||||
|
||||
void incrementRefresh() {
|
||||
auto incremented = ((REFRESH() & Mask7) + 1) & Mask7;
|
||||
REFRESH() = (REFRESH() & Bit7) | incremented;
|
||||
}
|
||||
uint8_t fetchByteData() {
|
||||
if (getM1())
|
||||
throw std::logic_error("M1 cannot be low");
|
||||
return fetchByte();
|
||||
}
|
||||
|
||||
void clearFlag(int flag) { F() &= ~flag; }
|
||||
void setFlag(int flag) { F() |= flag; }
|
||||
void incrementRefresh() {
|
||||
auto incremented = ((REFRESH() & Mask7) + 1) & Mask7;
|
||||
REFRESH() = (REFRESH() & Bit7) | incremented;
|
||||
}
|
||||
|
||||
void setFlag(int flag, int condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, uint32_t condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, bool condition) { condition ? setFlag(flag) : clearFlag(flag); }
|
||||
void clearFlag(int flag) { F() &= ~flag; }
|
||||
void setFlag(int flag) { F() |= flag; }
|
||||
|
||||
void clearFlag(int flag, int condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, uint32_t condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, bool condition) { condition ? clearFlag(flag) : setFlag(flag); }
|
||||
void setFlag(int flag, int condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, uint32_t condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, bool condition) { condition ? setFlag(flag) : clearFlag(flag); }
|
||||
|
||||
uint8_t& DISPLACED() {
|
||||
if (!(m_prefixDD || m_prefixFD))
|
||||
throw std::logic_error("Unprefixed indexed displacement requested");
|
||||
m_memory.ADDRESS().word = MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
|
||||
return m_memory.reference();
|
||||
}
|
||||
void clearFlag(int flag, int condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, uint32_t condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, bool condition) { condition ? clearFlag(flag) : setFlag(flag); }
|
||||
|
||||
uint8_t& R(int r) {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return B();
|
||||
case 1:
|
||||
return C();
|
||||
case 2:
|
||||
return D();
|
||||
case 3:
|
||||
return E();
|
||||
case 4:
|
||||
return ALT_HL().high;
|
||||
case 5:
|
||||
return ALT_HL().low;
|
||||
case 6:
|
||||
if (m_prefixDD || m_prefixFD) {
|
||||
m_displacement = fetchByteData();
|
||||
return DISPLACED();
|
||||
uint8_t& DISPLACED() {
|
||||
if (!(m_prefixDD || m_prefixFD))
|
||||
throw std::logic_error("Unprefixed indexed displacement requested");
|
||||
m_memory.ADDRESS().word = MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
uint8_t& R(int r) {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return B();
|
||||
case 1:
|
||||
return C();
|
||||
case 2:
|
||||
return D();
|
||||
case 3:
|
||||
return E();
|
||||
case 4:
|
||||
return ALT_HL().high;
|
||||
case 5:
|
||||
return ALT_HL().low;
|
||||
case 6:
|
||||
if (m_prefixDD || m_prefixFD) {
|
||||
m_displacement = fetchByteData();
|
||||
return DISPLACED();
|
||||
}
|
||||
m_memory.ADDRESS() = HL();
|
||||
return m_memory.reference();
|
||||
case 7:
|
||||
return A();
|
||||
}
|
||||
m_memory.ADDRESS() = HL();
|
||||
throw std::logic_error("Unhandled registry mechanism");
|
||||
}
|
||||
|
||||
uint8_t& R2(int r) {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return B();
|
||||
case 1:
|
||||
return C();
|
||||
case 2:
|
||||
return D();
|
||||
case 3:
|
||||
return E();
|
||||
case 4:
|
||||
return H();
|
||||
case 5:
|
||||
return L();
|
||||
case 6:
|
||||
m_memory.ADDRESS() = HL();
|
||||
return m_memory.reference();
|
||||
case 7:
|
||||
return A();
|
||||
}
|
||||
throw std::logic_error("Unhandled registry mechanism");
|
||||
}
|
||||
|
||||
register16_t& RP(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return sp;
|
||||
case HL_IDX:
|
||||
return ALT_HL();
|
||||
default:
|
||||
return m_registers[m_registerSet][rp];
|
||||
}
|
||||
}
|
||||
|
||||
register16_t& ALT_HL() {
|
||||
if (m_prefixDD)
|
||||
return IX();
|
||||
else if (m_prefixFD)
|
||||
return IY();
|
||||
return HL();
|
||||
}
|
||||
|
||||
register16_t& RP2(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return AF();
|
||||
case HL_IDX:
|
||||
return ALT_HL();
|
||||
default:
|
||||
return m_registers[m_registerSet][rp];
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getViaMemptr(register16_t address) {
|
||||
m_memory.ADDRESS() = address;
|
||||
MEMPTR().word = address.word + 1;
|
||||
return m_memory.reference();
|
||||
case 7:
|
||||
return A();
|
||||
}
|
||||
throw std::logic_error("Unhandled registry mechanism");
|
||||
}
|
||||
|
||||
uint8_t& R2(int r) {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return B();
|
||||
case 1:
|
||||
return C();
|
||||
case 2:
|
||||
return D();
|
||||
case 3:
|
||||
return E();
|
||||
case 4:
|
||||
return H();
|
||||
case 5:
|
||||
return L();
|
||||
case 6:
|
||||
m_memory.ADDRESS() = HL();
|
||||
return m_memory.reference();
|
||||
case 7:
|
||||
return A();
|
||||
void setViaMemptr(register16_t address, uint8_t value) {
|
||||
m_memory.ADDRESS() = address;
|
||||
m_memory.reference() = value;
|
||||
++address.word;
|
||||
MEMPTR().low = address.low;
|
||||
MEMPTR().high = value;
|
||||
}
|
||||
throw std::logic_error("Unhandled registry mechanism");
|
||||
}
|
||||
|
||||
register16_t& RP(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return sp;
|
||||
case HL_IDX:
|
||||
return ALT_HL();
|
||||
default:
|
||||
return m_registers[m_registerSet][rp];
|
||||
register16_t getWordViaMemptr(register16_t address) {
|
||||
register16_t returned;
|
||||
m_memory.ADDRESS() = address;
|
||||
returned.low = m_memory.reference();
|
||||
m_memory.ADDRESS().word++;
|
||||
returned.high = m_memory.reference();
|
||||
MEMPTR() = m_memory.ADDRESS();
|
||||
return returned;
|
||||
}
|
||||
}
|
||||
|
||||
register16_t& ALT_HL() {
|
||||
if (m_prefixDD)
|
||||
return IX();
|
||||
else if (m_prefixFD)
|
||||
return IY();
|
||||
return HL();
|
||||
}
|
||||
|
||||
register16_t& RP2(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return AF();
|
||||
case HL_IDX:
|
||||
return ALT_HL();
|
||||
default:
|
||||
return m_registers[m_registerSet][rp];
|
||||
void setWordViaMemptr(register16_t address, register16_t value) {
|
||||
m_memory.ADDRESS() = address;
|
||||
m_memory.reference() = value.low;
|
||||
m_memory.ADDRESS().word++;
|
||||
m_memory.reference() = value.high;
|
||||
MEMPTR() = m_memory.ADDRESS();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getViaMemptr(register16_t address) {
|
||||
m_memory.ADDRESS() = address;
|
||||
MEMPTR().word = address.word + 1;
|
||||
return m_memory.reference();
|
||||
}
|
||||
void setPcViaMemptr(register16_t address) {
|
||||
MEMPTR() = pc = address;
|
||||
}
|
||||
|
||||
void setViaMemptr(register16_t address, uint8_t value) {
|
||||
m_memory.ADDRESS() = address;
|
||||
m_memory.reference() = value;
|
||||
++address.word;
|
||||
MEMPTR().low = address.low;
|
||||
MEMPTR().high = value;
|
||||
}
|
||||
void addViaMemptr(register16_t& hl, register16_t operand) {
|
||||
MEMPTR().word = hl.word + 1;
|
||||
add(hl, operand);
|
||||
}
|
||||
|
||||
register16_t getWordViaMemptr(register16_t address) {
|
||||
register16_t returned;
|
||||
m_memory.ADDRESS() = address;
|
||||
returned.low = m_memory.reference();
|
||||
m_memory.ADDRESS().word++;
|
||||
returned.high = m_memory.reference();
|
||||
MEMPTR() = m_memory.ADDRESS();
|
||||
return returned;
|
||||
}
|
||||
void sbcViaMemptr(register16_t& hl, register16_t operand) {
|
||||
MEMPTR().word = hl.word + 1;
|
||||
sbc(hl, operand);
|
||||
}
|
||||
|
||||
void setWordViaMemptr(register16_t address, register16_t value) {
|
||||
m_memory.ADDRESS() = address;
|
||||
m_memory.reference() = value.low;
|
||||
m_memory.ADDRESS().word++;
|
||||
m_memory.reference() = value.high;
|
||||
MEMPTR() = m_memory.ADDRESS();
|
||||
}
|
||||
void adcViaMemptr(register16_t& hl, register16_t operand) {
|
||||
MEMPTR().word = hl.word + 1;
|
||||
adc(hl, operand);
|
||||
}
|
||||
|
||||
void setPcViaMemptr(register16_t address) {
|
||||
MEMPTR() = pc = address;
|
||||
}
|
||||
int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) {
|
||||
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
}
|
||||
|
||||
void addViaMemptr(register16_t& hl, register16_t operand) {
|
||||
MEMPTR().word = hl.word + 1;
|
||||
add(hl, operand);
|
||||
}
|
||||
void adjustHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableAdd[index & 0x7]);
|
||||
}
|
||||
|
||||
void sbcViaMemptr(register16_t& hl, register16_t operand) {
|
||||
MEMPTR().word = hl.word + 1;
|
||||
sbc(hl, operand);
|
||||
}
|
||||
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
|
||||
}
|
||||
|
||||
void adcViaMemptr(register16_t& hl, register16_t operand) {
|
||||
MEMPTR().word = hl.word + 1;
|
||||
adc(hl, operand);
|
||||
}
|
||||
void adjustOverflowAdd(uint8_t before, uint8_t value, uint8_t calculation) {
|
||||
adjustOverflowAdd(before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) {
|
||||
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
}
|
||||
void adjustOverflowAdd(int beforeNegative, int valueNegative, int afterNegative) {
|
||||
auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
|
||||
setFlag(VF, overflow);
|
||||
}
|
||||
|
||||
void adjustHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableAdd[index & 0x7]);
|
||||
}
|
||||
void adjustOverflowSub(uint8_t before, uint8_t value, uint8_t calculation) {
|
||||
adjustOverflowSub(before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
|
||||
}
|
||||
void adjustOverflowSub(int beforeNegative, int valueNegative, int afterNegative) {
|
||||
auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
|
||||
setFlag(VF, overflow);
|
||||
}
|
||||
|
||||
void adjustOverflowAdd(uint8_t before, uint8_t value, uint8_t calculation) {
|
||||
adjustOverflowAdd(before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
void executeCB(int x, int y, int z, int p, int q);
|
||||
void executeED(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
|
||||
void adjustOverflowAdd(int beforeNegative, int valueNegative, int afterNegative) {
|
||||
auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
|
||||
setFlag(VF, overflow);
|
||||
}
|
||||
void adjustSign(uint8_t value);
|
||||
void adjustZero(uint8_t value);
|
||||
void adjustParity(uint8_t value);
|
||||
void adjustSZ(uint8_t value);
|
||||
void adjustSZP(uint8_t value);
|
||||
void adjustXY(uint8_t value);
|
||||
void adjustSZPXY(uint8_t value);
|
||||
void adjustSZXY(uint8_t value);
|
||||
|
||||
void adjustOverflowSub(uint8_t before, uint8_t value, uint8_t calculation) {
|
||||
adjustOverflowSub(before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
void postIncrement(uint8_t value);
|
||||
void postDecrement(uint8_t value);
|
||||
|
||||
void adjustOverflowSub(int beforeNegative, int valueNegative, int afterNegative) {
|
||||
auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
|
||||
setFlag(VF, overflow);
|
||||
}
|
||||
void restart(uint8_t address);
|
||||
|
||||
void executeCB(int x, int y, int z, int p, int q);
|
||||
void executeED(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
void jrConditional(int conditional);
|
||||
void jrConditionalFlag(int flag);
|
||||
|
||||
void adjustSign(uint8_t value);
|
||||
void adjustZero(uint8_t value);
|
||||
void adjustParity(uint8_t value);
|
||||
void adjustSZ(uint8_t value);
|
||||
void adjustSZP(uint8_t value);
|
||||
void adjustXY(uint8_t value);
|
||||
void adjustSZPXY(uint8_t value);
|
||||
void adjustSZXY(uint8_t value);
|
||||
void ret();
|
||||
void retn();
|
||||
void reti();
|
||||
|
||||
void postIncrement(uint8_t value);
|
||||
void postDecrement(uint8_t value);
|
||||
void returnConditional(int condition);
|
||||
void returnConditionalFlag(int flag);
|
||||
|
||||
void restart(uint8_t address);
|
||||
void jumpConditional(int condition);
|
||||
void jumpConditionalFlag(int flag);
|
||||
|
||||
void jrConditional(int conditional);
|
||||
void jrConditionalFlag(int flag);
|
||||
void call(register16_t address);
|
||||
void callConditional(register16_t address, int condition);
|
||||
void callConditionalFlag(register16_t address, int flag);
|
||||
|
||||
void ret();
|
||||
void retn();
|
||||
void reti();
|
||||
void sbc(register16_t& operand, register16_t value);
|
||||
void adc(register16_t& operand, register16_t value);
|
||||
|
||||
void returnConditional(int condition);
|
||||
void returnConditionalFlag(int flag);
|
||||
void add(register16_t& operand, register16_t value);
|
||||
|
||||
void jumpConditional(int condition);
|
||||
void jumpConditionalFlag(int flag);
|
||||
void add(uint8_t& operand, uint8_t value, int carry = 0);
|
||||
void adc(uint8_t& operand, uint8_t value);
|
||||
void sub(uint8_t& operand, uint8_t value, int carry = 0);
|
||||
void sbc(uint8_t& operand, uint8_t value);
|
||||
void andr(uint8_t& operand, uint8_t value);
|
||||
void xorr(uint8_t& operand, uint8_t value);
|
||||
void orr(uint8_t& operand, uint8_t value);
|
||||
void compare(uint8_t value);
|
||||
|
||||
void call(register16_t address);
|
||||
void callConditional(register16_t address, int condition);
|
||||
void callConditionalFlag(register16_t address, int flag);
|
||||
void rlca();
|
||||
void rrca();
|
||||
void rla();
|
||||
void rra();
|
||||
|
||||
void sbc(register16_t& operand, register16_t value);
|
||||
void adc(register16_t& operand, register16_t value);
|
||||
void rlc(uint8_t& operand);
|
||||
void rrc(uint8_t& operand);
|
||||
void rl(uint8_t& operand);
|
||||
void rr(uint8_t& operand);
|
||||
void sla(uint8_t& operand);
|
||||
void sra(uint8_t& operand);
|
||||
void sll(uint8_t& operand);
|
||||
void srl(uint8_t& operand);
|
||||
|
||||
void add(register16_t& operand, register16_t value);
|
||||
void bit(int n, uint8_t& operand);
|
||||
void res(int n, uint8_t& operand);
|
||||
void set(int nit, uint8_t& operand);
|
||||
|
||||
void add(uint8_t& operand, uint8_t value, int carry = 0);
|
||||
void adc(uint8_t& operand, uint8_t value);
|
||||
void sub(uint8_t& operand, uint8_t value, int carry = 0);
|
||||
void sbc(uint8_t& operand, uint8_t value);
|
||||
void andr(uint8_t& operand, uint8_t value);
|
||||
void xorr(uint8_t& operand, uint8_t value);
|
||||
void orr(uint8_t& operand, uint8_t value);
|
||||
void compare(uint8_t value);
|
||||
void daa();
|
||||
|
||||
void rlca();
|
||||
void rrca();
|
||||
void rla();
|
||||
void rra();
|
||||
void scf();
|
||||
void ccf();
|
||||
void cpl();
|
||||
|
||||
void rlc(uint8_t& operand);
|
||||
void rrc(uint8_t& operand);
|
||||
void rl(uint8_t& operand);
|
||||
void rr(uint8_t& operand);
|
||||
void sla(uint8_t& operand);
|
||||
void sra(uint8_t& operand);
|
||||
void sll(uint8_t& operand);
|
||||
void srl(uint8_t& operand);
|
||||
void xhtl(register16_t& operand);
|
||||
void xhtl();
|
||||
|
||||
void bit(int n, uint8_t& operand);
|
||||
void res(int n, uint8_t& operand);
|
||||
void set(int nit, uint8_t& operand);
|
||||
void blockCompare();
|
||||
|
||||
void daa();
|
||||
void cpi();
|
||||
void cpir();
|
||||
|
||||
void scf();
|
||||
void ccf();
|
||||
void cpl();
|
||||
void cpd();
|
||||
void cpdr();
|
||||
|
||||
void xhtl(register16_t& operand);
|
||||
void xhtl();
|
||||
void blockLoad(register16_t source, register16_t destination);
|
||||
|
||||
void blockCompare();
|
||||
void ldi();
|
||||
void ldir();
|
||||
|
||||
void cpi();
|
||||
void cpir();
|
||||
void ldd();
|
||||
void lddr();
|
||||
|
||||
void cpd();
|
||||
void cpdr();
|
||||
void ini();
|
||||
void inir();
|
||||
|
||||
void blockLoad(register16_t source, register16_t destination);
|
||||
void ind();
|
||||
void indr();
|
||||
|
||||
void ldi();
|
||||
void ldir();
|
||||
void blockOut();
|
||||
|
||||
void ldd();
|
||||
void lddr();
|
||||
void outi();
|
||||
void otir();
|
||||
|
||||
void ini();
|
||||
void inir();
|
||||
void outd();
|
||||
void otdr();
|
||||
|
||||
void ind();
|
||||
void indr();
|
||||
void neg();
|
||||
|
||||
void blockOut();
|
||||
void rrd();
|
||||
void rld();
|
||||
|
||||
void outi();
|
||||
void otir();
|
||||
void writePort() {
|
||||
m_ports.write(m_memory.ADDRESS().low, m_memory.DATA());
|
||||
}
|
||||
|
||||
void outd();
|
||||
void otdr();
|
||||
|
||||
void neg();
|
||||
|
||||
void rrd();
|
||||
void rld();
|
||||
|
||||
void writePort() {
|
||||
m_ports.write(m_memory.ADDRESS().low, m_memory.DATA());
|
||||
}
|
||||
|
||||
void readPort() {
|
||||
m_memory.placeDATA(m_ports.read(m_memory.ADDRESS().low));
|
||||
}
|
||||
};
|
||||
void readPort() {
|
||||
m_memory.placeDATA(m_ports.read(m_memory.ADDRESS().low));
|
||||
}
|
||||
};
|
||||
}
|
@ -8,12 +8,12 @@
|
||||
#include "Memory.h"
|
||||
#include "Z80.h"
|
||||
|
||||
Disassembler::Disassembler() {
|
||||
EightBit::Disassembler::Disassembler() {
|
||||
// Disable exceptions where too many format arguments are available
|
||||
m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
|
||||
}
|
||||
|
||||
std::string Disassembler::state(Z80& cpu) {
|
||||
std::string EightBit::Disassembler::state(Z80& cpu) {
|
||||
|
||||
auto pc = cpu.getProgramCounter();
|
||||
auto sp = cpu.getStackPointer();
|
||||
@ -51,7 +51,7 @@ std::string Disassembler::state(Z80& cpu) {
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::RP(int rp) const {
|
||||
std::string EightBit::Disassembler::RP(int rp) const {
|
||||
switch (rp) {
|
||||
case 0:
|
||||
return "BC";
|
||||
@ -69,7 +69,7 @@ std::string Disassembler::RP(int rp) const {
|
||||
throw std::logic_error("Unhandled register pair");
|
||||
}
|
||||
|
||||
std::string Disassembler::RP2(int rp) const {
|
||||
std::string EightBit::Disassembler::RP2(int rp) const {
|
||||
switch (rp) {
|
||||
case 0:
|
||||
return "BC";
|
||||
@ -87,7 +87,7 @@ std::string Disassembler::RP2(int rp) const {
|
||||
throw std::logic_error("Unhandled register pair");
|
||||
}
|
||||
|
||||
std::string Disassembler::R(int r) const {
|
||||
std::string EightBit::Disassembler::R(int r) const {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return "B";
|
||||
@ -125,7 +125,7 @@ std::string Disassembler::R(int r) const {
|
||||
throw std::logic_error("Unhandled register");
|
||||
}
|
||||
|
||||
std::string Disassembler::cc(int flag) {
|
||||
std::string EightBit::Disassembler::cc(int flag) {
|
||||
switch (flag) {
|
||||
case 0:
|
||||
return "NZ";
|
||||
@ -147,7 +147,7 @@ std::string Disassembler::cc(int flag) {
|
||||
throw std::logic_error("Unhandled condition");
|
||||
}
|
||||
|
||||
std::string Disassembler::alu(int which) {
|
||||
std::string EightBit::Disassembler::alu(int which) {
|
||||
switch (which) {
|
||||
case 0: // ADD A,n
|
||||
return "ADD";
|
||||
@ -169,14 +169,14 @@ std::string Disassembler::alu(int which) {
|
||||
throw std::logic_error("Unhandled alu operation");
|
||||
}
|
||||
|
||||
std::string Disassembler::disassemble(const 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.getProgramCounter().word);
|
||||
return output.str();
|
||||
}
|
||||
|
||||
void Disassembler::disassemble(std::ostringstream& output, const Z80& cpu, uint16_t pc) {
|
||||
void EightBit::Disassembler::disassemble(std::ostringstream& output, const Z80& cpu, uint16_t pc) {
|
||||
|
||||
const auto& memory = cpu.getMemory();
|
||||
auto opcode = memory.peek(pc);
|
||||
@ -234,7 +234,7 @@ void Disassembler::disassemble(std::ostringstream& output, const Z80& cpu, uint1
|
||||
}
|
||||
}
|
||||
|
||||
void Disassembler::disassembleCB(
|
||||
void EightBit::Disassembler::disassembleCB(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
@ -284,7 +284,7 @@ void Disassembler::disassembleCB(
|
||||
}
|
||||
}
|
||||
|
||||
void Disassembler::disassembleED(
|
||||
void EightBit::Disassembler::disassembleED(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
@ -418,7 +418,7 @@ void Disassembler::disassembleED(
|
||||
}
|
||||
}
|
||||
|
||||
void Disassembler::disassembleOther(
|
||||
void EightBit::Disassembler::disassembleOther(
|
||||
std::ostringstream& output,
|
||||
const Z80& cpu,
|
||||
uint16_t pc,
|
||||
@ -674,13 +674,13 @@ void Disassembler::disassembleOther(
|
||||
}
|
||||
}
|
||||
|
||||
std::string Disassembler::flag(uint8_t value, int flag, const std::string& represents) {
|
||||
std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string& represents) {
|
||||
std::ostringstream output;
|
||||
output << (value & flag ? represents : "-");
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::flags(uint8_t value) {
|
||||
std::string EightBit::Disassembler::flags(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output
|
||||
<< flag(value, Z80::SF, "S")
|
||||
@ -694,31 +694,31 @@ std::string Disassembler::flags(uint8_t value) {
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::hex(uint8_t value) {
|
||||
std::string EightBit::Disassembler::hex(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::hex(uint16_t value) {
|
||||
std::string EightBit::Disassembler::hex(uint16_t value) {
|
||||
std::ostringstream output;
|
||||
output << std::hex << std::setw(4) << std::setfill('0') << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::binary(uint8_t value) {
|
||||
std::string EightBit::Disassembler::binary(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << std::bitset<8>(value);
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::decimal(uint8_t value) {
|
||||
std::string EightBit::Disassembler::decimal(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::invalid(uint8_t value) {
|
||||
std::string EightBit::Disassembler::invalid(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << "Invalid instruction: " << hex(value) << "(" << binary(value) << ")";
|
||||
return output.str();
|
||||
|
@ -1,38 +1,38 @@
|
||||
#include "stdafx.h"
|
||||
#include "InputOutput.h"
|
||||
|
||||
InputOutput::InputOutput() {
|
||||
EightBit::InputOutput::InputOutput() {
|
||||
}
|
||||
|
||||
uint8_t InputOutput::readInputPort(uint8_t port) {
|
||||
uint8_t EightBit::InputOutput::readInputPort(uint8_t port) {
|
||||
OnReadingPort(port);
|
||||
auto value = input[port];
|
||||
OnReadPort(port);
|
||||
return value;
|
||||
}
|
||||
|
||||
void InputOutput::writeOutputPort(uint8_t port, uint8_t value) {
|
||||
void EightBit::InputOutput::writeOutputPort(uint8_t port, uint8_t value) {
|
||||
OnWritingPort(port);
|
||||
output[port] = value;
|
||||
OnWrittenPort(port);
|
||||
}
|
||||
|
||||
void InputOutput::OnReadingPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnReadingPort(uint8_t port) {
|
||||
PortEventArgs event(port);
|
||||
ReadingPort.fire(event);
|
||||
}
|
||||
|
||||
void InputOutput::OnReadPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnReadPort(uint8_t port) {
|
||||
PortEventArgs event(port);
|
||||
ReadPort.fire(event);
|
||||
}
|
||||
|
||||
void InputOutput::OnWritingPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnWritingPort(uint8_t port) {
|
||||
PortEventArgs event(port);
|
||||
WritingPort.fire(event);
|
||||
}
|
||||
|
||||
void InputOutput::OnWrittenPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnWrittenPort(uint8_t port) {
|
||||
PortEventArgs event(port);
|
||||
WrittenPort.fire(event);
|
||||
}
|
||||
|
@ -2,28 +2,28 @@
|
||||
#include "Profiler.h"
|
||||
#include "Disassembler.h"
|
||||
|
||||
Profiler::Profiler() {
|
||||
EightBit::Profiler::Profiler() {
|
||||
std::fill(m_instructions.begin(), m_instructions.end(), 0);
|
||||
std::fill(m_addresses.begin(), m_addresses.end(), 0);
|
||||
}
|
||||
|
||||
Profiler::~Profiler() {
|
||||
EightBit::Profiler::~Profiler() {
|
||||
}
|
||||
|
||||
void Profiler::addInstruction(uint8_t instruction) {
|
||||
void EightBit::Profiler::addInstruction(uint8_t instruction) {
|
||||
m_instructions[instruction]++;
|
||||
}
|
||||
|
||||
void Profiler::addAddress(uint16_t address) {
|
||||
void EightBit::Profiler::addAddress(uint16_t address) {
|
||||
m_addresses[address]++;
|
||||
}
|
||||
|
||||
void Profiler::dump() const {
|
||||
void EightBit::Profiler::dump() const {
|
||||
dumpInstructionProfiles();
|
||||
dumpAddressProfiles();
|
||||
}
|
||||
|
||||
void Profiler::dumpInstructionProfiles() const {
|
||||
void EightBit::Profiler::dumpInstructionProfiles() const {
|
||||
std::cout << "** instructions" << std::endl;
|
||||
for (int i = 0; i < 0x100; ++i) {
|
||||
auto count = m_instructions[i];
|
||||
@ -32,7 +32,7 @@ void Profiler::dumpInstructionProfiles() const {
|
||||
}
|
||||
}
|
||||
|
||||
void Profiler::dumpAddressProfiles() const {
|
||||
void EightBit::Profiler::dumpAddressProfiles() const {
|
||||
std::cout << "** addresses" << std::endl;
|
||||
for (int i = 0; i < 0x10000; ++i) {
|
||||
auto count = m_addresses[i];
|
||||
|
179
Z80/src/Z80.cpp
179
Z80/src/Z80.cpp
@ -4,8 +4,9 @@
|
||||
// based on http://www.z80.info/decoding.htm
|
||||
// Half carry flag help from https://github.com/oubiwann/z80
|
||||
|
||||
Z80::Z80(Memory& memory, InputOutput& ports)
|
||||
: Processor(memory, ports),
|
||||
EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
|
||||
: Processor(memory),
|
||||
m_ports(ports),
|
||||
m_registerSet(0),
|
||||
m_accumulatorFlagsSet(0),
|
||||
m_refresh(0x7f),
|
||||
@ -23,12 +24,12 @@ Z80::Z80(Memory& memory, InputOutput& ports)
|
||||
MEMPTR().word = 0;
|
||||
}
|
||||
|
||||
void Z80::reset() {
|
||||
void EightBit::Z80::reset() {
|
||||
Processor::reset();
|
||||
IFF1() = IFF2() = false;
|
||||
}
|
||||
|
||||
void Z80::initialise() {
|
||||
void EightBit::Z80::initialise() {
|
||||
|
||||
Processor::initialise();
|
||||
|
||||
@ -64,15 +65,15 @@ void Z80::initialise() {
|
||||
|
||||
#pragma region Interrupt routines
|
||||
|
||||
void Z80::disableInterrupts() {
|
||||
void EightBit::Z80::disableInterrupts() {
|
||||
IFF1() = IFF2() = false;
|
||||
}
|
||||
|
||||
void Z80::enableInterrupts() {
|
||||
void EightBit::Z80::enableInterrupts() {
|
||||
IFF1() = IFF2() = true;
|
||||
}
|
||||
|
||||
int Z80::interrupt(bool maskable, uint8_t value) {
|
||||
int EightBit::Z80::interrupt(bool maskable, uint8_t value) {
|
||||
cycles = 0;
|
||||
if (!maskable || (maskable && IFF1())) {
|
||||
if (maskable) {
|
||||
@ -107,53 +108,53 @@ int Z80::interrupt(bool maskable, uint8_t value) {
|
||||
|
||||
#pragma region Flag manipulation helpers
|
||||
|
||||
void Z80::adjustSign(uint8_t value) {
|
||||
void EightBit::Z80::adjustSign(uint8_t value) {
|
||||
setFlag(SF, value & SF);
|
||||
}
|
||||
|
||||
void Z80::adjustZero(uint8_t value) {
|
||||
void EightBit::Z80::adjustZero(uint8_t value) {
|
||||
clearFlag(ZF, value);
|
||||
}
|
||||
|
||||
void Z80::adjustParity(uint8_t value) {
|
||||
void EightBit::Z80::adjustParity(uint8_t value) {
|
||||
static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
|
||||
auto set = lookup[highNibble(value)] + lookup[lowNibble(value)];
|
||||
clearFlag(PF, set % 2);
|
||||
}
|
||||
|
||||
void Z80::adjustSZ(uint8_t value) {
|
||||
void EightBit::Z80::adjustSZ(uint8_t value) {
|
||||
adjustSign(value);
|
||||
adjustZero(value);
|
||||
}
|
||||
|
||||
void Z80::adjustSZP(uint8_t value) {
|
||||
void EightBit::Z80::adjustSZP(uint8_t value) {
|
||||
adjustSZ(value);
|
||||
adjustParity(value);
|
||||
}
|
||||
|
||||
void Z80::adjustXY(uint8_t value) {
|
||||
void EightBit::Z80::adjustXY(uint8_t value) {
|
||||
setFlag(XF, value & XF);
|
||||
setFlag(YF, value & YF);
|
||||
}
|
||||
|
||||
void Z80::adjustSZPXY(uint8_t value) {
|
||||
void EightBit::Z80::adjustSZPXY(uint8_t value) {
|
||||
adjustSZP(value);
|
||||
adjustXY(value);
|
||||
}
|
||||
|
||||
void Z80::adjustSZXY(uint8_t value) {
|
||||
void EightBit::Z80::adjustSZXY(uint8_t value) {
|
||||
adjustSZ(value);
|
||||
adjustXY(value);
|
||||
}
|
||||
|
||||
void Z80::postIncrement(uint8_t value) {
|
||||
void EightBit::Z80::postIncrement(uint8_t value) {
|
||||
adjustSZXY(value);
|
||||
clearFlag(NF);
|
||||
setFlag(VF, value == Bit7);
|
||||
clearFlag(HC, lowNibble(value));
|
||||
}
|
||||
|
||||
void Z80::postDecrement(uint8_t value) {
|
||||
void EightBit::Z80::postDecrement(uint8_t value) {
|
||||
adjustSZXY(value);
|
||||
setFlag(NF);
|
||||
setFlag(VF, value == Mask7);
|
||||
@ -164,14 +165,14 @@ void Z80::postDecrement(uint8_t value) {
|
||||
|
||||
#pragma region PC manipulation: call/ret/jp/jr
|
||||
|
||||
void Z80::restart(uint8_t address) {
|
||||
void EightBit::Z80::restart(uint8_t address) {
|
||||
pushWord(pc);
|
||||
register16_t destination;
|
||||
destination.word = address;
|
||||
setPcViaMemptr(destination);
|
||||
}
|
||||
|
||||
void Z80::jrConditional(int conditional) {
|
||||
void EightBit::Z80::jrConditional(int conditional) {
|
||||
auto offset = (int8_t)fetchByteData();
|
||||
if (conditional) {
|
||||
register16_t destination;
|
||||
@ -181,7 +182,7 @@ void Z80::jrConditional(int conditional) {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::jrConditionalFlag(int flag) {
|
||||
void EightBit::Z80::jrConditionalFlag(int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
jrConditional(!(F() & ZF));
|
||||
@ -210,14 +211,14 @@ void Z80::jrConditionalFlag(int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::jumpConditional(int conditional) {
|
||||
void EightBit::Z80::jumpConditional(int conditional) {
|
||||
auto address = fetchWord();
|
||||
if (conditional)
|
||||
pc = address;
|
||||
MEMPTR() = address;
|
||||
}
|
||||
|
||||
void Z80::jumpConditionalFlag(int flag) {
|
||||
void EightBit::Z80::jumpConditionalFlag(int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
jumpConditional(!(F() & ZF));
|
||||
@ -246,27 +247,27 @@ void Z80::jumpConditionalFlag(int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::ret() {
|
||||
void EightBit::Z80::ret() {
|
||||
setPcViaMemptr(popWord());
|
||||
}
|
||||
|
||||
void Z80::retn() {
|
||||
void EightBit::Z80::retn() {
|
||||
ret();
|
||||
IFF1() = IFF2();
|
||||
}
|
||||
|
||||
void Z80::reti() {
|
||||
void EightBit::Z80::reti() {
|
||||
retn();
|
||||
}
|
||||
|
||||
void Z80::returnConditional(int condition) {
|
||||
void EightBit::Z80::returnConditional(int condition) {
|
||||
if (condition) {
|
||||
ret();
|
||||
cycles += 6;
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::returnConditionalFlag(int flag) {
|
||||
void EightBit::Z80::returnConditionalFlag(int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
returnConditional(!(F() & ZF));
|
||||
@ -295,12 +296,12 @@ void Z80::returnConditionalFlag(int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::call(register16_t address) {
|
||||
void EightBit::Z80::call(register16_t address) {
|
||||
pushWord(pc);
|
||||
pc = address;
|
||||
}
|
||||
|
||||
void Z80::callConditional(register16_t address, int condition) {
|
||||
void EightBit::Z80::callConditional(register16_t address, int condition) {
|
||||
if (condition) {
|
||||
call(address);
|
||||
cycles += 7;
|
||||
@ -308,7 +309,7 @@ void Z80::callConditional(register16_t address, int condition) {
|
||||
MEMPTR() = address;
|
||||
}
|
||||
|
||||
void Z80::callConditionalFlag(register16_t address, int flag) {
|
||||
void EightBit::Z80::callConditionalFlag(register16_t address, int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
callConditional(address, !(F() & ZF));
|
||||
@ -341,7 +342,7 @@ void Z80::callConditionalFlag(register16_t address, int flag) {
|
||||
|
||||
#pragma region 16-bit arithmetic
|
||||
|
||||
void Z80::sbc(register16_t& operand, register16_t value) {
|
||||
void EightBit::Z80::sbc(register16_t& operand, register16_t value) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
@ -362,7 +363,7 @@ void Z80::sbc(register16_t& operand, register16_t value) {
|
||||
adjustXY(operand.high);
|
||||
}
|
||||
|
||||
void Z80::adc(register16_t& operand, register16_t value) {
|
||||
void EightBit::Z80::adc(register16_t& operand, register16_t value) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
@ -383,7 +384,7 @@ void Z80::adc(register16_t& operand, register16_t value) {
|
||||
adjustXY(operand.high);
|
||||
}
|
||||
|
||||
void Z80::add(register16_t& operand, register16_t value) {
|
||||
void EightBit::Z80::add(register16_t& operand, register16_t value) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
@ -401,7 +402,7 @@ void Z80::add(register16_t& operand, register16_t value) {
|
||||
|
||||
#pragma region ALU
|
||||
|
||||
void Z80::add(uint8_t& operand, uint8_t value, int carry) {
|
||||
void EightBit::Z80::add(uint8_t& operand, uint8_t value, int carry) {
|
||||
|
||||
register16_t result;
|
||||
result.word = operand + value + carry;
|
||||
@ -416,11 +417,11 @@ void Z80::add(uint8_t& operand, uint8_t value, int carry) {
|
||||
adjustSZXY(operand);
|
||||
}
|
||||
|
||||
void Z80::adc(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::Z80::adc(uint8_t& operand, uint8_t value) {
|
||||
add(operand, value, F() & CF);
|
||||
}
|
||||
|
||||
void Z80::sub(uint8_t& operand, uint8_t value, int carry) {
|
||||
void EightBit::Z80::sub(uint8_t& operand, uint8_t value, int carry) {
|
||||
|
||||
register16_t result;
|
||||
result.word = operand - value - carry;
|
||||
@ -435,30 +436,30 @@ void Z80::sub(uint8_t& operand, uint8_t value, int carry) {
|
||||
adjustSZXY(operand);
|
||||
}
|
||||
|
||||
void Z80::sbc(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::Z80::sbc(uint8_t& operand, uint8_t value) {
|
||||
sub(operand, value, F() & CF);
|
||||
}
|
||||
|
||||
void Z80::andr(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::Z80::andr(uint8_t& operand, uint8_t value) {
|
||||
operand &= value;
|
||||
setFlag(HC);
|
||||
clearFlag(CF | NF);
|
||||
adjustSZPXY(operand);
|
||||
}
|
||||
|
||||
void Z80::xorr(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::Z80::xorr(uint8_t& operand, uint8_t value) {
|
||||
operand ^= value;
|
||||
clearFlag(HC | CF | NF);
|
||||
adjustSZPXY(operand);
|
||||
}
|
||||
|
||||
void Z80::orr(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::Z80::orr(uint8_t& operand, uint8_t value) {
|
||||
operand |= value;
|
||||
clearFlag(HC | CF | NF);
|
||||
adjustSZPXY(operand);
|
||||
}
|
||||
|
||||
void Z80::compare(uint8_t value) {
|
||||
void EightBit::Z80::compare(uint8_t value) {
|
||||
auto check = A();
|
||||
sub(check, value);
|
||||
adjustXY(value);
|
||||
@ -468,7 +469,7 @@ void Z80::compare(uint8_t value) {
|
||||
|
||||
#pragma region Shift and rotate
|
||||
|
||||
void Z80::rlc(uint8_t& operand) {
|
||||
void EightBit::Z80::rlc(uint8_t& operand) {
|
||||
auto carry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
setFlag(CF, carry);
|
||||
@ -477,7 +478,7 @@ void Z80::rlc(uint8_t& operand) {
|
||||
adjustXY(operand);
|
||||
}
|
||||
|
||||
void Z80::rrc(uint8_t& operand) {
|
||||
void EightBit::Z80::rrc(uint8_t& operand) {
|
||||
auto carry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
carry ? operand |= Bit7 : operand &= ~Bit7;
|
||||
@ -486,7 +487,7 @@ void Z80::rrc(uint8_t& operand) {
|
||||
adjustXY(operand);
|
||||
}
|
||||
|
||||
void Z80::rl(uint8_t& operand) {
|
||||
void EightBit::Z80::rl(uint8_t& operand) {
|
||||
auto oldCarry = F() & CF;
|
||||
auto newCarry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
@ -496,7 +497,7 @@ void Z80::rl(uint8_t& operand) {
|
||||
adjustXY(operand);
|
||||
}
|
||||
|
||||
void Z80::rr(uint8_t& operand) {
|
||||
void EightBit::Z80::rr(uint8_t& operand) {
|
||||
auto oldCarry = F() & CF;
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
@ -508,7 +509,7 @@ void Z80::rr(uint8_t& operand) {
|
||||
|
||||
//
|
||||
|
||||
void Z80::sla(uint8_t& operand) {
|
||||
void EightBit::Z80::sla(uint8_t& operand) {
|
||||
auto newCarry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
setFlag(CF, newCarry);
|
||||
@ -516,7 +517,7 @@ void Z80::sla(uint8_t& operand) {
|
||||
adjustXY(operand);
|
||||
}
|
||||
|
||||
void Z80::sra(uint8_t& operand) {
|
||||
void EightBit::Z80::sra(uint8_t& operand) {
|
||||
auto new7 = operand & Bit7;
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
@ -526,7 +527,7 @@ void Z80::sra(uint8_t& operand) {
|
||||
adjustXY(operand);
|
||||
}
|
||||
|
||||
void Z80::sll(uint8_t& operand) {
|
||||
void EightBit::Z80::sll(uint8_t& operand) {
|
||||
auto newCarry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
operand |= 1;
|
||||
@ -535,7 +536,7 @@ void Z80::sll(uint8_t& operand) {
|
||||
adjustXY(operand);
|
||||
}
|
||||
|
||||
void Z80::srl(uint8_t& operand) {
|
||||
void EightBit::Z80::srl(uint8_t& operand) {
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
operand &= ~Bit7; // clear bit 7
|
||||
@ -547,19 +548,19 @@ void Z80::srl(uint8_t& operand) {
|
||||
|
||||
//
|
||||
|
||||
void Z80::rlca() {
|
||||
void EightBit::Z80::rlca() {
|
||||
rlc(A());
|
||||
}
|
||||
|
||||
void Z80::rrca() {
|
||||
void EightBit::Z80::rrca() {
|
||||
rrc(A());
|
||||
}
|
||||
|
||||
void Z80::rla() {
|
||||
void EightBit::Z80::rla() {
|
||||
rl(A());
|
||||
}
|
||||
|
||||
void Z80::rra() {
|
||||
void EightBit::Z80::rra() {
|
||||
rr(A());
|
||||
}
|
||||
|
||||
@ -567,7 +568,7 @@ void Z80::rra() {
|
||||
|
||||
#pragma region BIT/SET/RES
|
||||
|
||||
void Z80::bit(int n, uint8_t& operand) {
|
||||
void EightBit::Z80::bit(int n, uint8_t& operand) {
|
||||
auto carry = F() & CF;
|
||||
uint8_t discarded = operand;
|
||||
andr(discarded, 1 << n);
|
||||
@ -575,12 +576,12 @@ void Z80::bit(int n, uint8_t& operand) {
|
||||
setFlag(CF, carry);
|
||||
}
|
||||
|
||||
void Z80::res(int n, uint8_t& operand) {
|
||||
void EightBit::Z80::res(int n, uint8_t& operand) {
|
||||
auto bit = 1 << n;
|
||||
operand &= ~bit;
|
||||
}
|
||||
|
||||
void Z80::set(int n, uint8_t& operand) {
|
||||
void EightBit::Z80::set(int n, uint8_t& operand) {
|
||||
auto bit = 1 << n;
|
||||
operand |= bit;
|
||||
}
|
||||
@ -589,7 +590,7 @@ void Z80::set(int n, uint8_t& operand) {
|
||||
|
||||
#pragma region Miscellaneous instructions
|
||||
|
||||
void Z80::neg() {
|
||||
void EightBit::Z80::neg() {
|
||||
auto original = A();
|
||||
A() = 0;
|
||||
sub(A(), original);
|
||||
@ -597,7 +598,7 @@ void Z80::neg() {
|
||||
setFlag(CF, original);
|
||||
}
|
||||
|
||||
void Z80::daa() {
|
||||
void EightBit::Z80::daa() {
|
||||
|
||||
uint8_t a = A();
|
||||
|
||||
@ -623,19 +624,19 @@ void Z80::daa() {
|
||||
A() = a;
|
||||
}
|
||||
|
||||
void Z80::cpl() {
|
||||
void EightBit::Z80::cpl() {
|
||||
A() = ~A();
|
||||
adjustXY(A());
|
||||
setFlag(HC | NF);
|
||||
}
|
||||
|
||||
void Z80::scf() {
|
||||
void EightBit::Z80::scf() {
|
||||
setFlag(CF);
|
||||
adjustXY(A());
|
||||
clearFlag(HC | NF);
|
||||
}
|
||||
|
||||
void Z80::ccf() {
|
||||
void EightBit::Z80::ccf() {
|
||||
auto carry = F() & CF;
|
||||
setFlag(HC, carry);
|
||||
clearFlag(CF, carry);
|
||||
@ -643,7 +644,7 @@ void Z80::ccf() {
|
||||
adjustXY(A());
|
||||
}
|
||||
|
||||
void Z80::xhtl(register16_t& operand) {
|
||||
void EightBit::Z80::xhtl(register16_t& operand) {
|
||||
m_memory.ADDRESS() = sp;
|
||||
MEMPTR().low = m_memory.reference();
|
||||
m_memory.reference() = operand.low;
|
||||
@ -654,7 +655,7 @@ void Z80::xhtl(register16_t& operand) {
|
||||
operand.high = MEMPTR().high;
|
||||
}
|
||||
|
||||
void Z80::xhtl() {
|
||||
void EightBit::Z80::xhtl() {
|
||||
if (m_prefixDD)
|
||||
xhtl(IX());
|
||||
else if (m_prefixFD)
|
||||
@ -669,7 +670,7 @@ void Z80::xhtl() {
|
||||
|
||||
#pragma region Block compare instructions
|
||||
|
||||
void Z80::blockCompare() {
|
||||
void EightBit::Z80::blockCompare() {
|
||||
|
||||
m_memory.ADDRESS() = HL();
|
||||
|
||||
@ -689,19 +690,19 @@ void Z80::blockCompare() {
|
||||
setFlag(XF, result & Bit3);
|
||||
}
|
||||
|
||||
void Z80::cpi() {
|
||||
void EightBit::Z80::cpi() {
|
||||
blockCompare();
|
||||
HL().word++;
|
||||
MEMPTR().word++;
|
||||
}
|
||||
|
||||
void Z80::cpd() {
|
||||
void EightBit::Z80::cpd() {
|
||||
blockCompare();
|
||||
HL().word--;
|
||||
MEMPTR().word--;
|
||||
}
|
||||
|
||||
void Z80::cpir() {
|
||||
void EightBit::Z80::cpir() {
|
||||
cpi();
|
||||
if ((F() & PF) && !(F() & ZF)) { // See CPI
|
||||
cycles += 5;
|
||||
@ -712,7 +713,7 @@ void Z80::cpir() {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::cpdr() {
|
||||
void EightBit::Z80::cpdr() {
|
||||
cpd();
|
||||
if ((F() & PF) && !(F() & ZF)) { // See CPD
|
||||
cycles += 5;
|
||||
@ -727,7 +728,7 @@ void Z80::cpdr() {
|
||||
|
||||
#pragma region Block load instructions
|
||||
|
||||
void Z80::blockLoad(register16_t source, register16_t destination) {
|
||||
void EightBit::Z80::blockLoad(register16_t source, register16_t destination) {
|
||||
m_memory.ADDRESS() = source;
|
||||
auto value = m_memory.reference();
|
||||
m_memory.ADDRESS() = destination;
|
||||
@ -739,19 +740,19 @@ void Z80::blockLoad(register16_t source, register16_t destination) {
|
||||
setFlag(PF, --BC().word);
|
||||
}
|
||||
|
||||
void Z80::ldd() {
|
||||
void EightBit::Z80::ldd() {
|
||||
blockLoad(HL(), DE());
|
||||
HL().word--;
|
||||
DE().word--;
|
||||
}
|
||||
|
||||
void Z80::ldi() {
|
||||
void EightBit::Z80::ldi() {
|
||||
blockLoad(HL(), DE());
|
||||
HL().word++;
|
||||
DE().word++;
|
||||
}
|
||||
|
||||
void Z80::ldir() {
|
||||
void EightBit::Z80::ldir() {
|
||||
ldi();
|
||||
if (F() & PF) { // See LDI
|
||||
cycles += 5;
|
||||
@ -760,7 +761,7 @@ void Z80::ldir() {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::lddr() {
|
||||
void EightBit::Z80::lddr() {
|
||||
ldd();
|
||||
if (F() & PF) { // See LDR
|
||||
cycles += 5;
|
||||
@ -773,7 +774,7 @@ void Z80::lddr() {
|
||||
|
||||
#pragma region Block input instructions
|
||||
|
||||
void Z80::ini() {
|
||||
void EightBit::Z80::ini() {
|
||||
auto bc = BC().word;
|
||||
m_memory.ADDRESS().word = bc;
|
||||
readPort();
|
||||
@ -785,7 +786,7 @@ void Z80::ini() {
|
||||
MEMPTR().word = ++bc;
|
||||
}
|
||||
|
||||
void Z80::ind() {
|
||||
void EightBit::Z80::ind() {
|
||||
auto bc = BC().word;
|
||||
m_memory.ADDRESS().word = bc;
|
||||
readPort();
|
||||
@ -797,7 +798,7 @@ void Z80::ind() {
|
||||
MEMPTR().word = --bc;
|
||||
}
|
||||
|
||||
void Z80::inir() {
|
||||
void EightBit::Z80::inir() {
|
||||
ini();
|
||||
if (!(F() & ZF)) { // See INI
|
||||
cycles += 5;
|
||||
@ -805,7 +806,7 @@ void Z80::inir() {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::indr() {
|
||||
void EightBit::Z80::indr() {
|
||||
ind();
|
||||
if (!(F() & ZF)) { // See IND
|
||||
cycles += 5;
|
||||
@ -817,7 +818,7 @@ void Z80::indr() {
|
||||
|
||||
#pragma region Block output instructions
|
||||
|
||||
void Z80::blockOut() {
|
||||
void EightBit::Z80::blockOut() {
|
||||
auto value = m_memory.reference();
|
||||
m_memory.ADDRESS().word = BC().word;
|
||||
writePort();
|
||||
@ -827,19 +828,19 @@ void Z80::blockOut() {
|
||||
adjustParity(((value + L()) & 7) ^ B());
|
||||
}
|
||||
|
||||
void Z80::outi() {
|
||||
void EightBit::Z80::outi() {
|
||||
m_memory.ADDRESS().word = HL().word++;
|
||||
blockOut();
|
||||
MEMPTR().word = BC().word + 1;
|
||||
}
|
||||
|
||||
void Z80::outd() {
|
||||
void EightBit::Z80::outd() {
|
||||
m_memory.ADDRESS().word = HL().word--;
|
||||
blockOut();
|
||||
MEMPTR().word = BC().word - 1;
|
||||
}
|
||||
|
||||
void Z80::otir() {
|
||||
void EightBit::Z80::otir() {
|
||||
outi();
|
||||
if (!(F() & ZF)) { // See OUTI
|
||||
cycles += 5;
|
||||
@ -847,7 +848,7 @@ void Z80::otir() {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::otdr() {
|
||||
void EightBit::Z80::otdr() {
|
||||
outd();
|
||||
if (!(F() & ZF)) { // See OUTD
|
||||
cycles += 5;
|
||||
@ -861,7 +862,7 @@ void Z80::otdr() {
|
||||
|
||||
#pragma region Nibble rotation
|
||||
|
||||
void Z80::rrd() {
|
||||
void EightBit::Z80::rrd() {
|
||||
auto accumulator = A();
|
||||
m_memory.ADDRESS() = HL();
|
||||
auto memory = m_memory.reference();
|
||||
@ -873,7 +874,7 @@ void Z80::rrd() {
|
||||
MEMPTR().word = HL().word + 1;
|
||||
}
|
||||
|
||||
void Z80::rld() {
|
||||
void EightBit::Z80::rld() {
|
||||
auto accumulator = A();
|
||||
m_memory.ADDRESS() = HL();
|
||||
auto memory = m_memory.reference();
|
||||
@ -887,14 +888,14 @@ void Z80::rld() {
|
||||
|
||||
#pragma endregion Nibble rotation
|
||||
|
||||
int Z80::step() {
|
||||
int EightBit::Z80::step() {
|
||||
ExecutingInstruction.fire(*this);
|
||||
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
||||
cycles = 0;
|
||||
return fetchExecute();
|
||||
}
|
||||
|
||||
int Z80::execute(uint8_t opcode) {
|
||||
int EightBit::Z80::execute(uint8_t opcode) {
|
||||
|
||||
if (!getM1())
|
||||
throw std::logic_error("M1 cannot be high");
|
||||
@ -924,7 +925,7 @@ int Z80::execute(uint8_t opcode) {
|
||||
return cycles;
|
||||
}
|
||||
|
||||
void Z80::executeCB(int x, int y, int z, int p, int q) {
|
||||
void EightBit::Z80::executeCB(int x, int y, int z, int p, int q) {
|
||||
switch (x) {
|
||||
case 0: // rot[y] r[z]
|
||||
switch (y) {
|
||||
@ -1049,7 +1050,7 @@ void Z80::executeCB(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::executeED(int x, int y, int z, int p, int q) {
|
||||
void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
case 3: // Invalid instruction, equivalent to NONI followed by NOP
|
||||
@ -1246,7 +1247,7 @@ void Z80::executeED(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
}
|
||||
|
||||
void Z80::executeOther(int x, int y, int z, int p, int q) {
|
||||
void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
switch (z) {
|
||||
|
170
Z80/src/Z80.vcxproj
Normal file
170
Z80/src/Z80.vcxproj
Normal file
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{01974F81-2750-45AF-B845-2C903A54A334}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Z80</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\inc\Disassembler.h" />
|
||||
<ClInclude Include="..\inc\InputOutput.h" />
|
||||
<ClInclude Include="..\inc\PortEventArgs.h" />
|
||||
<ClInclude Include="..\inc\Profiler.h" />
|
||||
<ClInclude Include="..\inc\Z80.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Disassembler.cpp" />
|
||||
<ClCompile Include="InputOutput.cpp" />
|
||||
<ClCompile Include="Profiler.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Z80.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\packages\boost.1.64.0.0\build\native\boost.targets" Condition="Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost.1.64.0.0\build\native\boost.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
53
Z80/src/Z80.vcxproj.filters
Normal file
53
Z80/src/Z80.vcxproj.filters
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\Disassembler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\InputOutput.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\PortEventArgs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\Profiler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\Z80.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Disassembler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InputOutput.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Profiler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Z80.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
4
Z80/src/packages.config
Normal file
4
Z80/src/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="boost" version="1.64.0.0" targetFramework="native" />
|
||||
</packages>
|
1
Z80/src/stdafx.cpp
Normal file
1
Z80/src/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
42
Z80/src/stdafx.h
Normal file
42
Z80/src/stdafx.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
//#include <SDL.h>
|
||||
//#include <SDL_mixer.h>
|
||||
//
|
||||
//#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
//#define HOST_LITTLE_ENDIAN
|
||||
//#endif
|
||||
//
|
||||
//#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
//#define HOST_BIG_ENDIAN
|
||||
//#endif
|
||||
//
|
||||
//#define RUN_TESTS
|
||||
////#define RUN_CPM
|
||||
////#define RUN_INVADERS
|
||||
//
|
||||
//#ifdef _MSC_VER
|
||||
//#pragma comment(lib, "SDL2.lib")
|
||||
//#pragma comment(lib, "SDL2main.lib")
|
||||
//#pragma comment(lib, "SDL2_mixer.lib")
|
||||
//#endif
|
84
Z80/test/Board.cpp
Normal file
84
Z80/test/Board.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "stdafx.h"
|
||||
#include "Board.h"
|
||||
#include "Disassembler.h"
|
||||
|
||||
Board::Board(const Configuration& configuration)
|
||||
: m_configuration(configuration),
|
||||
m_memory(0x3fff),
|
||||
m_cpu(EightBit::Z80(m_memory, m_ports)) {
|
||||
}
|
||||
|
||||
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_memory.ADDRESS().word = 5;
|
||||
m_memory.reference() = 0xc9; // ret
|
||||
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Cpm, this, std::placeholders::_1));
|
||||
|
||||
if (m_configuration.isProfileMode()) {
|
||||
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Profile, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
if (m_configuration.isDebugMode()) {
|
||||
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
m_cpu.initialise();
|
||||
m_cpu.setProgramCounter(m_configuration.getStartAddress());
|
||||
}
|
||||
|
||||
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Z80&) {
|
||||
auto pc = m_cpu.getProgramCounter();
|
||||
switch (pc.word) {
|
||||
case 0x0: // CP/M warm start
|
||||
m_cpu.halt();
|
||||
m_profiler.dump();
|
||||
break;
|
||||
case 0x5: // BDOS
|
||||
bdos();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Board::bdos() {
|
||||
auto c = m_cpu.C();
|
||||
switch (c) {
|
||||
case 0x2: {
|
||||
auto character = m_cpu.E();
|
||||
std::cout << character;
|
||||
break;
|
||||
}
|
||||
case 0x9:
|
||||
for (uint16_t i = m_cpu.DE().word; m_memory.peek(i) != '$'; ++i) {
|
||||
std::cout << m_memory.peek(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpu) {
|
||||
|
||||
const auto pc = cpu.getProgramCounter();
|
||||
|
||||
m_profiler.addAddress(pc.word);
|
||||
m_profiler.addInstruction(m_memory.peek(pc.word));
|
||||
}
|
||||
|
||||
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Z80& cpu) {
|
||||
|
||||
std::cerr
|
||||
<< EightBit::Disassembler::state(m_cpu)
|
||||
<< "\t"
|
||||
<< m_disassembler.disassemble(cpu)
|
||||
<< '\n';
|
||||
}
|
37
Z80/test/Board.h
Normal file
37
Z80/test/Board.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Memory.h"
|
||||
#include "InputOutput.h"
|
||||
#include "Configuration.h"
|
||||
#include "Profiler.h"
|
||||
#include "EventArgs.h"
|
||||
#include "Disassembler.h"
|
||||
#include "Z80.h"
|
||||
|
||||
class Board {
|
||||
public:
|
||||
Board(const Configuration& configuration);
|
||||
|
||||
EightBit::Memory& getMemory() { return m_memory; }
|
||||
const EightBit::Z80& getCPU() const { return m_cpu; }
|
||||
EightBit::Z80& getCPUMutable() { return m_cpu; }
|
||||
|
||||
void initialise();
|
||||
|
||||
private:
|
||||
const Configuration& m_configuration;
|
||||
EightBit::Memory m_memory;
|
||||
EightBit::InputOutput m_ports;
|
||||
EightBit::Z80 m_cpu;
|
||||
EightBit::Profiler m_profiler;
|
||||
EightBit::Disassembler m_disassembler;
|
||||
|
||||
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 bdos();
|
||||
};
|
8
Z80/test/Configuration.cpp
Normal file
8
Z80/test/Configuration.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
Configuration::Configuration()
|
||||
: m_debugMode(false),
|
||||
m_profileMode(false),
|
||||
m_romDirectory("roms") {
|
||||
}
|
42
Z80/test/Configuration.h
Normal file
42
Z80/test/Configuration.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Memory.h"
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
Configuration();
|
||||
|
||||
bool isDebugMode() const {
|
||||
return m_debugMode;
|
||||
}
|
||||
|
||||
void setDebugMode(bool value) {
|
||||
m_debugMode = value;
|
||||
}
|
||||
|
||||
bool isProfileMode() const {
|
||||
return m_profileMode;
|
||||
}
|
||||
|
||||
void setProfileMode(bool value) {
|
||||
m_profileMode = value;
|
||||
}
|
||||
|
||||
std::string getRomDirectory() const {
|
||||
return m_romDirectory;
|
||||
}
|
||||
|
||||
EightBit::register16_t getStartAddress() const {
|
||||
EightBit::register16_t returned;
|
||||
returned.word = 0x100;
|
||||
return returned;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_debugMode;
|
||||
bool m_profileMode;
|
||||
|
||||
std::string m_romDirectory;
|
||||
};
|
21
Z80/test/Game.cpp
Normal file
21
Z80/test/Game.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "stdafx.h"
|
||||
#include "Game.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
Game::Game(const Configuration& configuration)
|
||||
: m_configuration(configuration),
|
||||
m_board(configuration) {
|
||||
}
|
||||
|
||||
void Game::initialise() {
|
||||
m_board.initialise();
|
||||
}
|
||||
|
||||
void Game::runLoop() {
|
||||
auto& cpu = m_board.getCPUMutable();
|
||||
auto cycles = 0;
|
||||
while (!cpu.isHalted()) {
|
||||
cycles = cpu.step();
|
||||
}
|
||||
}
|
22
Z80/test/Game.h
Normal file
22
Z80/test/Game.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
//#include <stdexcept>
|
||||
//#include <string>
|
||||
//#include <memory>
|
||||
//#include <map>
|
||||
|
||||
#include "Board.h"
|
||||
|
||||
class Configuration;
|
||||
|
||||
class Game {
|
||||
public:
|
||||
Game(const Configuration& configuration);
|
||||
|
||||
void runLoop();
|
||||
void initialise();
|
||||
|
||||
private:
|
||||
const Configuration& m_configuration;
|
||||
mutable Board m_board;
|
||||
};
|
4
Z80/test/packages.config
Normal file
4
Z80/test/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="boost" version="1.64.0.0" targetFramework="native" />
|
||||
</packages>
|
BIN
Z80/test/roms/CPUTEST.COM
Normal file
BIN
Z80/test/roms/CPUTEST.COM
Normal file
Binary file not shown.
805
Z80/test/roms/TEST.ASM
Normal file
805
Z80/test/roms/TEST.ASM
Normal file
@ -0,0 +1,805 @@
|
||||
;***********************************************************************
|
||||
; MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC VERSION 1.0 (C) 1980
|
||||
;***********************************************************************
|
||||
; Load into virtual altair with: ALTAIR L=TEST.HEX
|
||||
; Then press F2 to view screen, and 'G' to execute the test.
|
||||
;
|
||||
;DONATED TO THE "SIG/M" CP/M USER'S GROUP BY:
|
||||
;KELLY SMITH, MICROCOSM ASSOCIATES
|
||||
;3055 WACO AVENUE
|
||||
;SIMI VALLEY, CALIFORNIA, 93065
|
||||
;(805) 527-9321 (MODEM, CP/M-NET (TM))
|
||||
;(805) 527-0518 (VERBAL)
|
||||
;
|
||||
CPU 8080
|
||||
ORG 00100H
|
||||
|
||||
LXI H, LOLZ
|
||||
CALL MSG
|
||||
JMP CPU ;JUMP TO 8080 CPU DIAGNOSTIC
|
||||
;
|
||||
LOLZ: DB "MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC VERSION 1.0 (C) 1980", 0dh, 0ah, 24h
|
||||
;
|
||||
BDOS EQU 00005H ;BDOS ENTRY TO CP/M
|
||||
WBOOT: JMP 0
|
||||
;
|
||||
;MESSAGE OUTPUT ROUTINE
|
||||
;
|
||||
MSG: MOV A,M ; Get data
|
||||
CPI '$' ; End?
|
||||
RZ
|
||||
CALL PCHAR ; Output
|
||||
INX H ; Next
|
||||
JMP MSG ; Do all
|
||||
;
|
||||
;
|
||||
;CHARACTER OUTPUT ROUTINE
|
||||
;
|
||||
PCHAR: PUSH PSW
|
||||
PUSH D
|
||||
PUSH H
|
||||
MOV E,A
|
||||
MVI C,2
|
||||
CALL BDOS
|
||||
POP H
|
||||
POP D
|
||||
POP PSW
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
BYTEO: PUSH PSW
|
||||
CALL BYTO1
|
||||
MOV E,A
|
||||
CALL PCHAR
|
||||
POP PSW
|
||||
CALL BYTO2
|
||||
MOV E,A
|
||||
JMP PCHAR
|
||||
BYTO1: RRC
|
||||
RRC
|
||||
RRC
|
||||
RRC
|
||||
BYTO2: ANI 0FH
|
||||
CPI 0AH
|
||||
JM BYTO3
|
||||
ADI 7
|
||||
BYTO3: ADI 30H
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
;************************************************************
|
||||
; MESSAGE TABLE FOR OPERATIONAL CPU TEST
|
||||
;************************************************************
|
||||
;
|
||||
OKCPU: DB 0DH,0AH
|
||||
DB "CPU IS OPERATIONAL$"
|
||||
;
|
||||
NGCPU: DB 0DH,0AH
|
||||
DB " CPU HAS FAILED! ERROR EXIT=$"
|
||||
;
|
||||
;
|
||||
;
|
||||
;************************************************************
|
||||
; 8080/8085 CPU TEST/DIAGNOSTIC
|
||||
;************************************************************
|
||||
;
|
||||
;NOTE: (1) PROGRAM ASSUMES "CALL",AND "LXI SP" INSTRUCTIONS WORK!
|
||||
;
|
||||
; (2) INSTRUCTIONS NOT TESTED ARE "HLT","DI","EI",
|
||||
; AND "RST 0" THRU "RST 7"
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST JUMP INSTRUCTIONS AND FLAGS
|
||||
;
|
||||
CPU: LXI SP,STACK ;SET THE STACK POINTER
|
||||
ANI 0 ;INITIALIZE A REG. AND CLEAR ALL FLAGS
|
||||
JZ J010 ;TEST "JZ"
|
||||
CALL CPUER
|
||||
J010: JNC J020 ;TEST "JNC"
|
||||
CALL CPUER
|
||||
J020: JPE J030 ;TEST "JPE"
|
||||
CALL CPUER
|
||||
J030: JP J040 ;TEST "JP"
|
||||
CALL CPUER
|
||||
J040: JNZ J050 ;TEST "JNZ"
|
||||
JC J050 ;TEST "JC"
|
||||
JPO J050 ;TEST "JPO"
|
||||
JM J050 ;TEST "JM"
|
||||
JMP J060 ;TEST "JMP" (IT'S A LITTLE LATE,BUT WHAT THE HELL!
|
||||
J050: CALL CPUER
|
||||
J060: ADI 6 ;A=6,C=0,P=1,S=0,Z=0
|
||||
JNZ J070 ;TEST "JNZ"
|
||||
CALL CPUER
|
||||
J070: JC J080 ;TEST "JC"
|
||||
JPO J080 ;TEST "JPO"
|
||||
JP J090 ;TEST "JP"
|
||||
J080: CALL CPUER
|
||||
J090: ADI 070H ;A=76H,C=0,P=0,S=0,Z=0
|
||||
JPO J100 ;TEST "JPO"
|
||||
CALL CPUER
|
||||
J100: JM J110 ;TEST "JM"
|
||||
JZ J110 ;TEST "JZ"
|
||||
JNC J120 ;TEST "JNC"
|
||||
J110: CALL CPUER
|
||||
J120: ADI 081H ;A=F7H,C=0,P=0,S=1,Z=0
|
||||
JM J130 ;TEST "JM"
|
||||
CALL CPUER
|
||||
J130: JZ J140 ;TEST "JZ"
|
||||
JC J140 ;TEST "JC"
|
||||
JPO J150 ;TEST "JPO"
|
||||
J140: CALL CPUER
|
||||
J150: ADI 0FEH ;A=F5H,C=1,P=1,S=1,Z=0
|
||||
JC J160 ;TEST "JC"
|
||||
CALL CPUER
|
||||
J160: JZ J170 ;TEST "JZ"
|
||||
JPO J170 ;TEST "JPO"
|
||||
JM AIMM ;TEST "JM"
|
||||
J170: CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST ACCUMULATOR IMMEDIATE INSTRUCTIONS
|
||||
;
|
||||
AIMM: CPI 0 ;A=F5H,C=0,Z=0
|
||||
JC CPIE ;TEST "CPI" FOR RE-SET CARRY
|
||||
JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
CPI 0F5H ;A=F5H,C=0,Z=1
|
||||
JC CPIE ;TEST "CPI" FOR RE-SET CARRY ("ADI")
|
||||
JNZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
CPI 0FFH ;A=F5H,C=1,Z=0
|
||||
JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
JC ACII ;TEST "CPI" FOR SET CARRY
|
||||
CPIE: CALL CPUER
|
||||
ACII: ACI 00AH ;A=F5H+0AH+CARRY(1)=0,C=1
|
||||
ACI 00AH ;A=0+0AH+CARRY(0)=0BH,C=0
|
||||
CPI 00BH
|
||||
JZ SUII ;TEST "ACI"
|
||||
CALL CPUER
|
||||
SUII: SUI 00CH ;A=FFH,C=0
|
||||
SUI 00FH ;A=F0H,C=1
|
||||
CPI 0F0H
|
||||
JZ SBII ;TEST "SUI"
|
||||
CALL CPUER
|
||||
SBII: SBI 0F1H ;A=F0H-0F1H-CARRY(0)=FFH,C=1
|
||||
SBI 00EH ;A=FFH-OEH-CARRY(1)=F0H,C=0
|
||||
CPI 0F0H
|
||||
JZ ANII ;TEST "SBI"
|
||||
CALL CPUER
|
||||
ANII: ANI 055H ;A=F0H<AND>55H=50H,C=0,P=1,S=0,Z=0
|
||||
CPI 050H
|
||||
JZ ORII ;TEST "ANI"
|
||||
CALL CPUER
|
||||
ORII: ORI 03AH ;A=50H<OR>3AH=7AH,C=0,P=0,S=0,Z=0
|
||||
CPI 07AH
|
||||
JZ XRII ;TEST "ORI"
|
||||
CALL CPUER
|
||||
XRII: XRI 00FH ;A=7AH<XOR>0FH=75H,C=0,P=0,S=0,Z=0
|
||||
CPI 075H
|
||||
JZ C010 ;TEST "XRI"
|
||||
CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST CALLS AND RETURNS
|
||||
;
|
||||
C010: ANI 000H ;A=0,C=0,P=1,S=0,Z=1
|
||||
CC CPUER ;TEST "CC"
|
||||
CPO CPUER ;TEST "CPO"
|
||||
CM CPUER ;TEST "CM"
|
||||
CNZ CPUER ;TEST "CNZ"
|
||||
CPI 000H
|
||||
JZ C020 ;A=0,C=0,P=0,S=0,Z=1
|
||||
CALL CPUER
|
||||
C020: SUI 077H ;A=89H,C=1,P=0,S=1,Z=0
|
||||
CNC CPUER ;TEST "CNC"
|
||||
CPE CPUER ;TEST "CPE"
|
||||
CP CPUER ;TEST "CP"
|
||||
CZ CPUER ;TEST "CZ"
|
||||
CPI 089H
|
||||
JZ C030 ;TEST FOR "CALLS" TAKING BRANCH
|
||||
CALL CPUER
|
||||
C030: ANI 0FFH ;SET FLAGS BACK!
|
||||
CPO CPOI ;TEST "CPO"
|
||||
CPI 0D9H
|
||||
JZ MOVI ;TEST "CALL" SEQUENCE SUCCESS
|
||||
CALL CPUER
|
||||
CPOI: RPE ;TEST "RPE"
|
||||
ADI 010H ;A=99H,C=0,P=0,S=1,Z=0
|
||||
CPE CPEI ;TEST "CPE"
|
||||
ADI 002H ;A=D9H,C=0,P=0,S=1,Z=0
|
||||
RPO ;TEST "RPO"
|
||||
CALL CPUER
|
||||
CPEI: RPO ;TEST "RPO"
|
||||
ADI 020H ;A=B9H,C=0,P=0,S=1,Z=0
|
||||
CM CMI ;TEST "CM"
|
||||
ADI 004H ;A=D7H,C=0,P=1,S=1,Z=0
|
||||
RPE ;TEST "RPE"
|
||||
CALL CPUER
|
||||
CMI: RP ;TEST "RP"
|
||||
ADI 080H ;A=39H,C=1,P=1,S=0,Z=0
|
||||
CP TCPI ;TEST "CP"
|
||||
ADI 080H ;A=D3H,C=0,P=0,S=1,Z=0
|
||||
RM ;TEST "RM"
|
||||
CALL CPUER
|
||||
TCPI: RM ;TEST "RM"
|
||||
ADI 040H ;A=79H,C=0,P=0,S=0,Z=0
|
||||
CNC CNCI ;TEST "CNC"
|
||||
ADI 040H ;A=53H,C=0,P=1,S=0,Z=0
|
||||
RP ;TEST "RP"
|
||||
CALL CPUER
|
||||
CNCI: RC ;TEST "RC"
|
||||
ADI 08FH ;A=08H,C=1,P=0,S=0,Z=0
|
||||
CC CCI ;TEST "CC"
|
||||
SUI 002H ;A=13H,C=0,P=0,S=0,Z=0
|
||||
RNC ;TEST "RNC"
|
||||
CALL CPUER
|
||||
CCI: RNC ;TEST "RNC"
|
||||
ADI 0F7H ;A=FFH,C=0,P=1,S=1,Z=0
|
||||
CNZ CNZI ;TEST "CNZ"
|
||||
ADI 0FEH ;A=15H,C=1,P=0,S=0,Z=0
|
||||
RC ;TEST "RC"
|
||||
CALL CPUER
|
||||
CNZI: RZ ;TEST "RZ"
|
||||
ADI 001H ;A=00H,C=1,P=1,S=0,Z=1
|
||||
CZ CZI ;TEST "CZ"
|
||||
ADI 0D0H ;A=17H,C=1,P=1,S=0,Z=0
|
||||
RNZ ;TEST "RNZ"
|
||||
CALL CPUER
|
||||
CZI: RNZ ;TEST "RNZ"
|
||||
ADI 047H ;A=47H,C=0,P=1,S=0,Z=0
|
||||
CPI 047H ;A=47H,C=0,P=1,S=0,Z=1
|
||||
RZ ;TEST "RZ"
|
||||
CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST "MOV","INR",AND "DCR" INSTRUCTIONS
|
||||
;
|
||||
MOVI: MVI A,077H
|
||||
INR A
|
||||
MOV B,A
|
||||
INR B
|
||||
MOV C,B
|
||||
DCR C
|
||||
MOV D,C
|
||||
MOV E,D
|
||||
MOV H,E
|
||||
MOV L,H
|
||||
MOV A,L ;TEST "MOV" A,L,H,E,D,C,B,A
|
||||
DCR A
|
||||
MOV C,A
|
||||
MOV E,C
|
||||
MOV L,E
|
||||
MOV B,L
|
||||
MOV D,B
|
||||
MOV H,D
|
||||
MOV A,H ;TEST "MOV" A,H,D,B,L,E,C,A
|
||||
MOV D,A
|
||||
INR D
|
||||
MOV L,D
|
||||
MOV C,L
|
||||
INR C
|
||||
MOV H,C
|
||||
MOV B,H
|
||||
DCR B
|
||||
MOV E,B
|
||||
MOV A,E ;TEST "MOV" A,E,B,H,C,L,D,A
|
||||
MOV E,A
|
||||
INR E
|
||||
MOV B,E
|
||||
MOV H,B
|
||||
INR H
|
||||
MOV C,H
|
||||
MOV L,C
|
||||
MOV D,L
|
||||
DCR D
|
||||
MOV A,D ;TEST "MOV" A,D,L,C,H,B,E,A
|
||||
MOV H,A
|
||||
DCR H
|
||||
MOV D,H
|
||||
MOV B,D
|
||||
MOV L,B
|
||||
INR L
|
||||
MOV E,L
|
||||
DCR E
|
||||
MOV C,E
|
||||
MOV A,C ;TEST "MOV" A,C,E,L,B,D,H,A
|
||||
MOV L,A
|
||||
DCR L
|
||||
MOV H,L
|
||||
MOV E,H
|
||||
MOV D,E
|
||||
MOV C,D
|
||||
MOV B,C
|
||||
MOV A,B
|
||||
CPI 077H
|
||||
CNZ CPUER ;TEST "MOV" A,B,C,D,E,H,L,A
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST ARITHMETIC AND LOGIC INSTRUCTIONS
|
||||
;
|
||||
XRA A
|
||||
MVI B,001H
|
||||
MVI C,003H
|
||||
MVI D,007H
|
||||
MVI E,00FH
|
||||
MVI H,01FH
|
||||
MVI L,03FH
|
||||
ADD B
|
||||
ADD C
|
||||
ADD D
|
||||
ADD E
|
||||
ADD H
|
||||
ADD L
|
||||
ADD A
|
||||
CPI 0F0H
|
||||
CNZ CPUER ;TEST "ADD" B,C,D,E,H,L,A
|
||||
SUB B
|
||||
SUB C
|
||||
SUB D
|
||||
SUB E
|
||||
SUB H
|
||||
SUB L
|
||||
CPI 078H
|
||||
CNZ CPUER ;TEST "SUB" B,C,D,E,H,L
|
||||
SUB A
|
||||
CNZ CPUER ;TEST "SUB" A
|
||||
MVI A,080H
|
||||
ADD A
|
||||
MVI B,001H
|
||||
MVI C,002H
|
||||
MVI D,003H
|
||||
MVI E,004H
|
||||
MVI H,005H
|
||||
MVI L,006H
|
||||
ADC B
|
||||
MVI B,080H
|
||||
ADD B
|
||||
ADD B
|
||||
ADC C
|
||||
ADD B
|
||||
ADD B
|
||||
ADC D
|
||||
ADD B
|
||||
ADD B
|
||||
ADC E
|
||||
ADD B
|
||||
ADD B
|
||||
ADC H
|
||||
ADD B
|
||||
ADD B
|
||||
ADC L
|
||||
ADD B
|
||||
ADD B
|
||||
ADC A
|
||||
CPI 037H
|
||||
CNZ CPUER ;TEST "ADC" B,C,D,E,H,L,A
|
||||
MVI A,080H
|
||||
ADD A
|
||||
MVI B,001H
|
||||
SBB B
|
||||
MVI B,0FFH
|
||||
ADD B
|
||||
SBB C
|
||||
ADD B
|
||||
SBB D
|
||||
ADD B
|
||||
SBB E
|
||||
ADD B
|
||||
SBB H
|
||||
ADD B
|
||||
SBB L
|
||||
CPI 0E0H
|
||||
CNZ CPUER ;TEST "SBB" B,C,D,E,H,L
|
||||
MVI A,080H
|
||||
ADD A
|
||||
SBB A
|
||||
CPI 0FFH
|
||||
CNZ CPUER ;TEST "SBB" A
|
||||
MVI A,0FFH
|
||||
MVI B,0FEH
|
||||
MVI C,0FCH
|
||||
MVI D,0EFH
|
||||
MVI E,07FH
|
||||
MVI H,0F4H
|
||||
MVI L,0BFH
|
||||
ANA A
|
||||
ANA C
|
||||
ANA D
|
||||
ANA E
|
||||
ANA H
|
||||
ANA L
|
||||
ANA A
|
||||
CPI 024H
|
||||
CNZ CPUER ;TEST "ANA" B,C,D,E,H,L,A
|
||||
XRA A
|
||||
MVI B,001H
|
||||
MVI C,002H
|
||||
MVI D,004H
|
||||
MVI E,008H
|
||||
MVI H,010H
|
||||
MVI L,020H
|
||||
ORA B
|
||||
ORA C
|
||||
ORA D
|
||||
ORA E
|
||||
ORA H
|
||||
ORA L
|
||||
ORA A
|
||||
CPI 03FH
|
||||
CNZ CPUER ;TEST "ORA" B,C,D,E,H,L,A
|
||||
MVI A,000H
|
||||
MVI H,08FH
|
||||
MVI L,04FH
|
||||
XRA B
|
||||
XRA C
|
||||
XRA D
|
||||
XRA E
|
||||
XRA H
|
||||
XRA L
|
||||
CPI 0CFH
|
||||
CNZ CPUER ;TEST "XRA" B,C,D,E,H,L
|
||||
XRA A
|
||||
CNZ CPUER ;TEST "XRA" A
|
||||
MVI B,044H
|
||||
MVI C,045H
|
||||
MVI D,046H
|
||||
MVI E,047H
|
||||
MVI H,(TEMP0/0FFH) ;HIGH BYTE OF TEST MEMORY LOCATION
|
||||
MVI L,(TEMP0&0FFH) ;LOW BYTE OF TEST MEMORY LOCATION
|
||||
MOV M,B
|
||||
MVI B,000H
|
||||
MOV B,M
|
||||
MVI A,044H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "MOV" M,B AND B,M
|
||||
MOV M,D
|
||||
MVI D,000H
|
||||
MOV D,M
|
||||
MVI A,046H
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "MOV" M,D AND D,M
|
||||
MOV M,E
|
||||
MVI E,000H
|
||||
MOV E,M
|
||||
MVI A,047H
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "MOV" M,E AND E,M
|
||||
MOV M,H
|
||||
MVI H,(TEMP0/0FFH)
|
||||
MVI L,(TEMP0&0FFH)
|
||||
MOV H,M
|
||||
MVI A,(TEMP0/0FFH)
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "MOV" M,H AND H,M
|
||||
MOV M,L
|
||||
MVI H,(TEMP0/0FFH)
|
||||
MVI L,(TEMP0&0FFH)
|
||||
MOV L,M
|
||||
MVI A,(TEMP0&0FFH)
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "MOV" M,L AND L,M
|
||||
MVI H,(TEMP0/0FFH)
|
||||
MVI L,(TEMP0&0FFH)
|
||||
MVI A,032H
|
||||
MOV M,A
|
||||
CMP M
|
||||
CNZ CPUER ;TEST "MOV" M,A
|
||||
ADD M
|
||||
CPI 064H
|
||||
CNZ CPUER ;TEST "ADD" M
|
||||
XRA A
|
||||
MOV A,M
|
||||
CPI 032H
|
||||
CNZ CPUER ;TEST "MOV" A,M
|
||||
MVI H,(TEMP0/0FFH)
|
||||
MVI L,(TEMP0&0FFH)
|
||||
MOV A,M
|
||||
SUB M
|
||||
CNZ CPUER ;TEST "SUB" M
|
||||
MVI A,080H
|
||||
ADD A
|
||||
ADC M
|
||||
CPI 033H
|
||||
CNZ CPUER ;TEST "ADC" M
|
||||
MVI A,080H
|
||||
ADD A
|
||||
SBB M
|
||||
CPI 0CDH
|
||||
CNZ CPUER ;TEST "SBB" M
|
||||
ANA M
|
||||
CNZ CPUER ;TEST "ANA" M
|
||||
MVI A,025H
|
||||
ORA M
|
||||
CPI 037H
|
||||
CNZ CPUER ;TEST "ORA" M
|
||||
XRA M
|
||||
CPI 005H
|
||||
CNZ CPUER ;TEST "XRA" M
|
||||
MVI M,055H
|
||||
INR M
|
||||
DCR M
|
||||
ADD M
|
||||
CPI 05AH
|
||||
CNZ CPUER ;TEST "INR","DCR",AND "MVI" M
|
||||
LXI B,12FFH
|
||||
LXI D,12FFH
|
||||
LXI H,12FFH
|
||||
INX B
|
||||
INX D
|
||||
INX H
|
||||
MVI A,013H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" B
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" D
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" H
|
||||
MVI A,000H
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" B
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" D
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" H
|
||||
DCX B
|
||||
DCX D
|
||||
DCX H
|
||||
MVI A,012H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "DCX" B
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "DCX" D
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DCX" H
|
||||
MVI A,0FFH
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "DCX" B
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "DCX" D
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DCX" H
|
||||
STA TEMP0
|
||||
XRA A
|
||||
LDA TEMP0
|
||||
CPI 0FFH
|
||||
CNZ CPUER ;TEST "LDA" AND "STA"
|
||||
LHLD TEMPP
|
||||
SHLD TEMP0
|
||||
LDA TEMPP
|
||||
MOV B,A
|
||||
LDA TEMP0
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LHLD" AND "SHLD"
|
||||
LDA TEMPP+1
|
||||
MOV B,A
|
||||
LDA TEMP0+1
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LHLD" AND "SHLD"
|
||||
MVI A,0AAH
|
||||
STA TEMP0
|
||||
MOV B,H
|
||||
MOV C,L
|
||||
XRA A
|
||||
LDAX B
|
||||
CPI 0AAH
|
||||
CNZ CPUER ;TEST "LDAX" B
|
||||
INR A
|
||||
STAX B
|
||||
LDA TEMP0
|
||||
CPI 0ABH
|
||||
CNZ CPUER ;TEST "STAX" B
|
||||
MVI A,077H
|
||||
STA TEMP0
|
||||
LHLD TEMPP
|
||||
LXI D,00000H
|
||||
XCHG
|
||||
XRA A
|
||||
LDAX D
|
||||
CPI 077H
|
||||
CNZ CPUER ;TEST "LDAX" D AND "XCHG"
|
||||
XRA A
|
||||
ADD H
|
||||
ADD L
|
||||
CNZ CPUER ;TEST "XCHG"
|
||||
MVI A,0CCH
|
||||
STAX D
|
||||
LDA TEMP0
|
||||
CPI 0CCH
|
||||
STAX D
|
||||
LDA TEMP0
|
||||
CPI 0CCH
|
||||
CNZ CPUER ;TEST "STAX" D
|
||||
LXI H,07777H
|
||||
DAD H
|
||||
MVI A,0EEH
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DAD" H
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DAD" H
|
||||
LXI H,05555H
|
||||
LXI B,0FFFFH
|
||||
DAD B
|
||||
MVI A,055H
|
||||
CNC CPUER ;TEST "DAD" B
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DAD" B
|
||||
MVI A,054H
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DAD" B
|
||||
LXI H,0AAAAH
|
||||
LXI D,03333H
|
||||
DAD D
|
||||
MVI A,0DDH
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DAD" D
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DAD" B
|
||||
STC
|
||||
CNC CPUER ;TEST "STC"
|
||||
CMC
|
||||
CC CPUER ;TEST "CMC
|
||||
MVI A,0AAH
|
||||
CMA
|
||||
CPI 055H
|
||||
CNZ CPUER ;TEST "CMA"
|
||||
ORA A ;RE-SET AUXILIARY CARRY
|
||||
DAA
|
||||
CPI 055H
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
MVI A,088H
|
||||
ADD A
|
||||
DAA
|
||||
CPI 076H
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
XRA A
|
||||
MVI A,0AAH
|
||||
DAA
|
||||
CNC CPUER ;TEST "DAA"
|
||||
CPI 010H
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
XRA A
|
||||
MVI A,09AH
|
||||
DAA
|
||||
CNC CPUER ;TEST "DAA"
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
STC
|
||||
MVI A,042H
|
||||
RLC
|
||||
CC CPUER ;TEST "RLC" FOR RE-SET CARRY
|
||||
RLC
|
||||
CNC CPUER ;TEST "RLC" FOR SET CARRY
|
||||
CPI 009H
|
||||
CNZ CPUER ;TEST "RLC" FOR ROTATION
|
||||
RRC
|
||||
CNC CPUER ;TEST "RRC" FOR SET CARRY
|
||||
RRC
|
||||
CPI 042H
|
||||
CNZ CPUER ;TEST "RRC" FOR ROTATION
|
||||
RAL
|
||||
RAL
|
||||
CNC CPUER ;TEST "RAL" FOR SET CARRY
|
||||
CPI 008H
|
||||
CNZ CPUER ;TEST "RAL" FOR ROTATION
|
||||
RAR
|
||||
RAR
|
||||
CC CPUER ;TEST "RAR" FOR RE-SET CARRY
|
||||
CPI 002H
|
||||
CNZ CPUER ;TEST "RAR" FOR ROTATION
|
||||
LXI B,01234H
|
||||
LXI D,0AAAAH
|
||||
LXI H,05555H
|
||||
XRA A
|
||||
PUSH B
|
||||
PUSH D
|
||||
PUSH H
|
||||
PUSH PSW
|
||||
LXI B,00000H
|
||||
LXI D,00000H
|
||||
LXI H,00000H
|
||||
MVI A,0C0H
|
||||
ADI 0F0H
|
||||
POP PSW
|
||||
POP H
|
||||
POP D
|
||||
POP B
|
||||
CC CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
CNZ CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
CPO CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
CM CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
MVI A,012H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "PUSH B" AND "POP B"
|
||||
MVI A,034H
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "PUSH B" AND "POP B"
|
||||
MVI A,0AAH
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "PUSH D" AND "POP D"
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "PUSH D" AND "POP D"
|
||||
MVI A,055H
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "PUSH H" AND "POP H"
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "PUSH H" AND "POP H"
|
||||
LXI H,00000H
|
||||
DAD SP
|
||||
SHLD SAVSTK ;SAVE THE "OLD" STACK-POINTER!
|
||||
LXI SP,TEMP4
|
||||
DCX SP
|
||||
DCX SP
|
||||
INX SP
|
||||
DCX SP
|
||||
MVI A,055H
|
||||
STA TEMP2
|
||||
CMA
|
||||
STA TEMP3
|
||||
POP B
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LXI","DAD","INX",AND "DCX" SP
|
||||
CMA
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "LXI","DAD","INX", AND "DCX" SP
|
||||
LXI H,TEMP4
|
||||
SPHL
|
||||
LXI H,07733H
|
||||
DCX SP
|
||||
DCX SP
|
||||
XTHL
|
||||
LDA TEMP3
|
||||
CPI 077H
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
LDA TEMP2
|
||||
CPI 033H
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
MVI A,055H
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
CMA
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
LHLD SAVSTK ;RESTORE THE "OLD" STACK-POINTER
|
||||
SPHL
|
||||
LXI H,CPUOK
|
||||
PCHL ;TEST "PCHL"
|
||||
;
|
||||
;
|
||||
;
|
||||
CPUER: LXI H,NGCPU ;OUTPUT "CPU HAS FAILED ERROR EXIT=" TO CONSOLE
|
||||
CALL MSG
|
||||
XTHL
|
||||
MOV A,H
|
||||
CALL BYTEO ;SHOW ERROR EXIT ADDRESS HIGH BYTE
|
||||
MOV A,L
|
||||
CALL BYTEO ;SHOW ERROR EXIT ADDRESS LOW BYTE
|
||||
JMP WBOOT ;EXIT TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
CPUOK: LXI H,OKCPU ;OUTPUT "CPU IS OPERATIONAL" TO CONSOLE
|
||||
CALL MSG
|
||||
JMP WBOOT ;EXIT TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
TEMPP: DW TEMP0 ;POINTER USED TO TEST "LHLD","SHLD",
|
||||
; AND "LDAX" INSTRUCTIONS
|
||||
;
|
||||
TEMP0: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP1: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP2 DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP3: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP4: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
SAVSTK: DS 2 ;TEMPORARY STACK-POINTER STORAGE LOCATION
|
||||
;
|
||||
;
|
||||
;
|
||||
STACK EQU TEMPP+256 ;DE-BUG STACK POINTER STORAGE AREA
|
||||
;
|
||||
END
|
||||
|
BIN
Z80/test/roms/TEST.COM
Normal file
BIN
Z80/test/roms/TEST.COM
Normal file
Binary file not shown.
BIN
Z80/test/roms/prelim.com
Normal file
BIN
Z80/test/roms/prelim.com
Normal file
Binary file not shown.
343
Z80/test/roms/prelim.z80
Normal file
343
Z80/test/roms/prelim.z80
Normal file
@ -0,0 +1,343 @@
|
||||
.title 'Preliminary Z80 tests'
|
||||
|
||||
; prelim.z80 - Preliminary Z80 tests
|
||||
; Copyright (C) 1994 Frank D. Cringle
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; as published by the Free Software Foundation; either version 2
|
||||
; of the License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
; These tests have two goals. To start with, we assume the worst and
|
||||
; successively test the instructions needed to continue testing.
|
||||
; Then we try to test all instructions which cannot be handled by
|
||||
; zexlax - the crc-based instruction exerciser.
|
||||
|
||||
; Initially errors are 'reported' by jumping to 0. This should reboot
|
||||
; cp/m, so if the program terminates without any output one of the
|
||||
; early tests failed. Later errors are reported by outputting an
|
||||
; address via the bdos conout routine. The address can be located in
|
||||
; a listing of this program.
|
||||
|
||||
; If the program runs to completion it displays a suitable message.
|
||||
|
||||
aseg
|
||||
org 100h
|
||||
|
||||
start: ld a,1 ; test simple compares and z/nz jumps
|
||||
cp 2
|
||||
jp z,0
|
||||
cp 1
|
||||
jp nz,0
|
||||
jp lab0
|
||||
halt ; emergency exit
|
||||
db 0ffh
|
||||
|
||||
lab0: call lab2 ; does a simple call work?
|
||||
lab1: jp 0 ; fail
|
||||
|
||||
lab2: pop hl ; check return address
|
||||
ld a,h
|
||||
cp high lab1
|
||||
jp z,lab3
|
||||
jp 0
|
||||
lab3: ld a,l
|
||||
cp low lab1
|
||||
jp z,lab4
|
||||
jp 0
|
||||
|
||||
; test presence and uniqueness of all machine registers
|
||||
; (except ir)
|
||||
lab4: ld sp,regs1
|
||||
pop af
|
||||
pop bc
|
||||
pop de
|
||||
pop hl
|
||||
ex af,af'
|
||||
exx
|
||||
pop af
|
||||
pop bc
|
||||
pop de
|
||||
pop hl
|
||||
pop ix
|
||||
pop iy
|
||||
ld sp,regs2+20
|
||||
push iy
|
||||
push ix
|
||||
push hl
|
||||
push de
|
||||
push bc
|
||||
push af
|
||||
ex af,af'
|
||||
exx
|
||||
push hl
|
||||
push de
|
||||
push bc
|
||||
push af
|
||||
|
||||
v: set 0
|
||||
rept 20
|
||||
ld a,(regs2+v/2)
|
||||
v: set v+2
|
||||
cp v
|
||||
jp nz,0
|
||||
endm
|
||||
|
||||
; test access to memory via (hl)
|
||||
ld hl,hlval
|
||||
ld a,(hl)
|
||||
cp 0a5h
|
||||
jp nz,0
|
||||
ld hl,hlval+1
|
||||
ld a,(hl)
|
||||
cp 03ch
|
||||
jp nz,0
|
||||
|
||||
; test unconditional return
|
||||
ld sp,stack
|
||||
ld hl,reta
|
||||
push hl
|
||||
ret
|
||||
jp 0
|
||||
|
||||
; test instructions needed for hex output
|
||||
reta: ld a,255
|
||||
and a,15
|
||||
cp 15
|
||||
jp nz,0
|
||||
ld a,05ah
|
||||
and 15
|
||||
cp 00ah
|
||||
jp nz,0
|
||||
rrca
|
||||
cp 005h
|
||||
jp nz,0
|
||||
rrca
|
||||
cp 082h
|
||||
jp nz,0
|
||||
rrca
|
||||
cp 041h
|
||||
jp nz,0
|
||||
rrca
|
||||
cp 0a0h
|
||||
jp nz,0
|
||||
ld hl,01234h
|
||||
push hl
|
||||
pop bc
|
||||
ld a,b
|
||||
cp 012h
|
||||
jp nz,0
|
||||
ld a,c
|
||||
cp 034h
|
||||
jp nz,0
|
||||
|
||||
; from now on we can report errors by displaying an address
|
||||
|
||||
; test conditional call, ret, jp, jr
|
||||
tcond: macro flag,pcond,ncond,rel
|
||||
ld hl,&flag
|
||||
push hl
|
||||
pop af
|
||||
call &pcond,lab1&pcond
|
||||
jp error
|
||||
lab1&pcond: pop hl
|
||||
ld hl,0d7h xor &flag
|
||||
push hl
|
||||
pop af
|
||||
call &ncond,lab2&pcond
|
||||
jp error
|
||||
lab2&pcond: pop hl
|
||||
ld hl,lab3&pcond
|
||||
push hl
|
||||
ld hl,&flag
|
||||
push hl
|
||||
pop af
|
||||
ret &pcond
|
||||
call error
|
||||
lab3&pcond: ld hl,lab4&pcond
|
||||
push hl
|
||||
ld hl,0d7h xor &flag
|
||||
push hl
|
||||
pop af
|
||||
ret &ncond
|
||||
call error
|
||||
lab4&pcond: ld hl,&flag
|
||||
push hl
|
||||
pop af
|
||||
jp &pcond,lab5&pcond
|
||||
call error
|
||||
lab5&pcond: ld hl,0d7h xor &flag
|
||||
push hl
|
||||
pop af
|
||||
jp &ncond,lab6&pcond
|
||||
call error
|
||||
lab6&pcond:
|
||||
if &rel
|
||||
ld hl,&flag
|
||||
push hl
|
||||
pop af
|
||||
jr &pcond,lab7&pcond
|
||||
call error
|
||||
lab7&pcond: ld hl,0d7h xor &flag
|
||||
push hl
|
||||
pop af
|
||||
jr &ncond,lab8&pcond
|
||||
call error
|
||||
lab8&pcond:
|
||||
endif
|
||||
endm
|
||||
|
||||
tcond 1,c,nc,1
|
||||
tcond 4,pe,po,0
|
||||
tcond 040h,z,nz,1
|
||||
tcond 080h,m,p,0
|
||||
|
||||
; test indirect jumps
|
||||
ld hl,lab5
|
||||
jp (hl)
|
||||
call error
|
||||
lab5: ld hl,lab6
|
||||
push hl
|
||||
pop ix
|
||||
jp (ix)
|
||||
call error
|
||||
lab6: ld hl,lab7
|
||||
push hl
|
||||
pop iy
|
||||
jp (iy)
|
||||
call error
|
||||
|
||||
; djnz (and (partially) inc a, inc hl)
|
||||
lab7: ld a,0a5h
|
||||
ld b,4
|
||||
lab8: rrca
|
||||
djnz lab8
|
||||
cp 05ah
|
||||
call nz,error
|
||||
ld b,16
|
||||
lab9: inc a
|
||||
djnz lab9
|
||||
cp 06ah
|
||||
call nz,error
|
||||
ld b,0
|
||||
ld hl,0
|
||||
lab10: inc hl
|
||||
djnz lab10
|
||||
ld a,h
|
||||
cp 1
|
||||
call nz,error
|
||||
ld a,l
|
||||
cp 0
|
||||
call nz,error
|
||||
|
||||
; relative addressing
|
||||
reladr: macro r
|
||||
ld &r,hlval
|
||||
ld a,(&r)
|
||||
cp 0a5h
|
||||
call nz,error
|
||||
ld a,(&r+1)
|
||||
cp 03ch
|
||||
call nz,error
|
||||
inc &r
|
||||
ld a,(&r-1)
|
||||
cp 0a5h
|
||||
call nz,error
|
||||
ld &r,hlval-126
|
||||
ld a,(&r+127)
|
||||
cp 03ch
|
||||
call nz,error
|
||||
ld &r,hlval+128
|
||||
ld a,(&r-128)
|
||||
cp 0a5h
|
||||
call nz,error
|
||||
endm
|
||||
|
||||
reladr ix
|
||||
reladr iy
|
||||
|
||||
allok: ld de,okmsg
|
||||
ld c,9
|
||||
call 5
|
||||
jp 0
|
||||
|
||||
okmsg: db 'Preliminary tests complete$'
|
||||
|
||||
|
||||
; display address at top of stack and exit
|
||||
error: pop bc
|
||||
ld h,high hextab
|
||||
ld a,b
|
||||
rrca
|
||||
rrca
|
||||
rrca
|
||||
rrca
|
||||
and 15
|
||||
ld l,a
|
||||
ld a,(hl)
|
||||
call conout
|
||||
ld a,b
|
||||
and 15
|
||||
ld l,a
|
||||
ld a,(hl)
|
||||
call conout
|
||||
ld a,c
|
||||
rrca
|
||||
rrca
|
||||
rrca
|
||||
rrca
|
||||
and 15
|
||||
ld l,a
|
||||
ld a,(hl)
|
||||
call conout
|
||||
ld a,c
|
||||
and 15
|
||||
ld l,a
|
||||
ld a,(hl)
|
||||
call conout
|
||||
ld a,13
|
||||
call conout
|
||||
ld a,10
|
||||
call conout
|
||||
jp 0
|
||||
|
||||
conout: push af
|
||||
push bc
|
||||
push de
|
||||
push hl
|
||||
ld c,2
|
||||
ld e,a
|
||||
call 5
|
||||
pop hl
|
||||
pop de
|
||||
pop bc
|
||||
pop af
|
||||
ret
|
||||
|
||||
v: set 0
|
||||
regs1: rept 20
|
||||
v: set v+2
|
||||
db v
|
||||
endm
|
||||
|
||||
regs2: ds 20,0
|
||||
|
||||
hlval: db 0a5h,03ch
|
||||
|
||||
; skip to next page boundary
|
||||
org (($+255)/256)*256
|
||||
hextab: db '0123456789abcdef'
|
||||
ds 240
|
||||
stack: equ $
|
||||
|
||||
end
|
BIN
Z80/test/roms/zexall.com
Normal file
BIN
Z80/test/roms/zexall.com
Normal file
Binary file not shown.
BIN
Z80/test/roms/zexdoc.com
Normal file
BIN
Z80/test/roms/zexdoc.com
Normal file
Binary file not shown.
1546
Z80/test/roms/zexdoc.z80
Normal file
1546
Z80/test/roms/zexdoc.z80
Normal file
File diff suppressed because it is too large
Load Diff
1
Z80/test/stdafx.cpp
Normal file
1
Z80/test/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
24
Z80/test/stdafx.h
Normal file
24
Z80/test/stdafx.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
//#include <SDL.h>
|
||||
//#include <SDL_mixer.h>
|
||||
//
|
||||
//#ifdef _MSC_VER
|
||||
//#pragma comment(lib, "SDL2.lib")
|
||||
//#pragma comment(lib, "SDL2main.lib")
|
||||
//#pragma comment(lib, "SDL2_mixer.lib")
|
||||
//#endif
|
19
Z80/test/test.cpp
Normal file
19
Z80/test/test.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "stdafx.h"
|
||||
#include "Game.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
int main(int, char*[]) {
|
||||
|
||||
Configuration configuration;
|
||||
|
||||
#ifdef _DEBUG
|
||||
configuration.setDebugMode(true);
|
||||
configuration.setProfileMode(true);
|
||||
#endif
|
||||
|
||||
Game game(configuration);
|
||||
game.initialise();
|
||||
game.runLoop();
|
||||
|
||||
return 0;
|
||||
}
|
185
Z80/test/test_Z80.vcxproj
Normal file
185
Z80/test/test_Z80.vcxproj
Normal file
@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>test_Z80</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link />
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link />
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Board.h" />
|
||||
<ClInclude Include="Configuration.h" />
|
||||
<ClInclude Include="Game.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Board.cpp" />
|
||||
<ClCompile Include="Configuration.cpp" />
|
||||
<ClCompile Include="Game.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="test.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\EightBit.vcxproj">
|
||||
<Project>{a9c24bd9-0cb4-4c84-b09b-46b815f9da47}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\src\Z80.vcxproj">
|
||||
<Project>{01974f81-2750-45af-b845-2c903a54a334}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\packages\boost.1.64.0.0\build\native\boost.targets" Condition="Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost.1.64.0.0\build\native\boost.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
47
Z80/test/test_Z80.vcxproj.filters
Normal file
47
Z80/test/test_Z80.vcxproj.filters
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Board.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Configuration.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Game.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Board.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Configuration.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Game.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="test.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
10
inc/Memory.h
10
inc/Memory.h
@ -30,7 +30,7 @@ namespace EightBit {
|
||||
public:
|
||||
Memory(uint16_t addressMask);
|
||||
|
||||
virtual uint16_t& ADDRESS() { return m_address; }
|
||||
virtual register16_t& ADDRESS() { return m_address; }
|
||||
virtual uint8_t& DATA() { return *m_data; }
|
||||
|
||||
virtual uint8_t& placeDATA(uint8_t value) {
|
||||
@ -48,21 +48,21 @@ namespace EightBit {
|
||||
virtual uint16_t peekWord(uint16_t address) const;
|
||||
|
||||
virtual uint8_t get(uint16_t address) {
|
||||
ADDRESS() = address;
|
||||
ADDRESS().word = address;
|
||||
return reference();
|
||||
}
|
||||
|
||||
virtual register16_t getWord(uint16_t address);
|
||||
|
||||
virtual void set(uint16_t address, uint8_t value) {
|
||||
ADDRESS() = address;
|
||||
ADDRESS().word = address;
|
||||
reference() = value;
|
||||
}
|
||||
|
||||
virtual void setWord(uint16_t address, register16_t value);
|
||||
|
||||
virtual uint8_t& reference() {
|
||||
uint16_t effective = ADDRESS() & m_addressMask;
|
||||
uint16_t effective = ADDRESS().word & m_addressMask;
|
||||
return m_locked[effective] ? placeDATA(m_bus[effective]) : referenceDATA(m_bus[effective]);
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ namespace EightBit {
|
||||
|
||||
uint16_t m_addressMask; // Mirror
|
||||
uint8_t m_temporary; // Used to simulate ROM
|
||||
uint16_t m_address;
|
||||
register16_t m_address;
|
||||
uint8_t* m_data;
|
||||
|
||||
int loadMemory(const std::string& path, uint16_t offset);
|
||||
|
@ -47,10 +47,6 @@ namespace EightBit {
|
||||
static uint8_t promoteNibble(uint8_t value) { return value << 4; }
|
||||
static uint8_t demoteNibble(uint8_t value) { return highNibble(value); }
|
||||
|
||||
static uint16_t makeWord(uint8_t low, uint8_t high) {
|
||||
return (high << 8) | low;
|
||||
}
|
||||
|
||||
Processor(Memory& memory);
|
||||
|
||||
const Memory& getMemory() const { return m_memory; }
|
||||
@ -68,14 +64,6 @@ namespace EightBit {
|
||||
|
||||
void reset();
|
||||
|
||||
virtual register16_t getWord(uint16_t address) const {
|
||||
return m_memory.getWord(address);
|
||||
}
|
||||
|
||||
virtual void setWord(uint16_t address, register16_t value) {
|
||||
m_memory.setWord(address, value);
|
||||
}
|
||||
|
||||
protected:
|
||||
Memory& m_memory;
|
||||
|
||||
@ -86,17 +74,23 @@ namespace EightBit {
|
||||
|
||||
bool m_halted;
|
||||
|
||||
void push(uint8_t value);
|
||||
void pushWord(register16_t value);
|
||||
|
||||
uint8_t pop();
|
||||
register16_t popWord();
|
||||
|
||||
uint8_t fetchByte() {
|
||||
return m_memory.get(pc.word++);
|
||||
m_memory.ADDRESS() = pc;
|
||||
pc.word++;
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
uint16_t fetchWord() {
|
||||
auto value = getWord(pc.word);
|
||||
pc.word += 2;
|
||||
return value.word;
|
||||
register16_t fetchWord() {
|
||||
register16_t returned;
|
||||
returned.low = fetchByte();
|
||||
returned.high = fetchByte();
|
||||
return returned;
|
||||
}
|
||||
};
|
||||
}
|
@ -7,18 +7,20 @@
|
||||
#include <algorithm>
|
||||
|
||||
EightBit::Memory::Memory(uint16_t addressMask)
|
||||
: m_address(0),
|
||||
m_addressMask(addressMask),
|
||||
m_data(&(m_bus[m_address])) {}
|
||||
: m_addressMask(addressMask) {
|
||||
m_address.word = 0;
|
||||
m_data = &(m_bus[m_address.word]);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Memory::peek(uint16_t address) const {
|
||||
return m_bus[address];
|
||||
}
|
||||
|
||||
uint16_t EightBit::Memory::peekWord(uint16_t address) const {
|
||||
auto low = peek(address);
|
||||
auto high = peek(address + 1);
|
||||
return Processor::makeWord(low, high);
|
||||
register16_t returned;
|
||||
returned.low = peek(address);
|
||||
returned.high = peek(address + 1);
|
||||
return returned.word;
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::Memory::getWord(uint16_t address) {
|
||||
|
@ -5,7 +5,8 @@ EightBit::Processor::Processor(Memory& memory)
|
||||
: m_memory(memory),
|
||||
cycles(0),
|
||||
m_halted(false) {
|
||||
pc.word = sp.word = 0;
|
||||
sp.word = 0xffff;
|
||||
pc.word = 0;
|
||||
}
|
||||
|
||||
void EightBit::Processor::reset() {
|
||||
@ -13,17 +14,30 @@ void EightBit::Processor::reset() {
|
||||
}
|
||||
|
||||
void EightBit::Processor::initialise() {
|
||||
sp.word = 0;
|
||||
sp.word = 0xffff;
|
||||
reset();
|
||||
}
|
||||
|
||||
void EightBit::Processor::push(uint8_t value) {
|
||||
sp.word--;
|
||||
m_memory.ADDRESS() = sp;
|
||||
m_memory.reference() = value;
|
||||
}
|
||||
|
||||
void EightBit::Processor::pushWord(register16_t value) {
|
||||
sp.word -= 2;
|
||||
setWord(sp.word, value);
|
||||
push(value.high);
|
||||
push(value.low);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::pop() {
|
||||
m_memory.ADDRESS() = sp;
|
||||
sp.word++;
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::Processor::popWord() {
|
||||
auto value = getWord(sp.word);
|
||||
sp.word += 2;
|
||||
return value;
|
||||
register16_t returned;
|
||||
returned.low = pop();
|
||||
returned.high = pop();
|
||||
return returned;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user