Remove some "tricksy" code from the Z80 emulator chain.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon
2018-04-14 09:39:06 +01:00
parent 4b4f6b1a49
commit 9de0f597f6
14 changed files with 140 additions and 141 deletions

View File

@@ -19,7 +19,7 @@ namespace EightBit {
bool high : 1; bool high : 1;
uint8_t variable : 7; uint8_t variable : 7;
refresh_t(uint8_t value) refresh_t(const uint8_t value)
: high((value & Bit7) != 0), : high((value & Bit7) != 0),
variable(value & Mask7) variable(value & Mask7)
{ } { }
@@ -125,7 +125,7 @@ namespace EightBit {
m_displacement = fetchByte(); m_displacement = fetchByte();
} }
uint8_t R(int r, uint8_t a) { uint8_t R(const int r, const uint8_t a) {
ASSUME(r >= 0); ASSUME(r >= 0);
ASSUME(r <= 7); ASSUME(r <= 7);
switch (r) { switch (r) {
@@ -142,7 +142,7 @@ namespace EightBit {
case 5: case 5:
return HL2().low; return HL2().low;
case 6: case 6:
return BUS().read(LIKELY(!m_displaced) ? HL().word : displacedAddress()); return BUS().read(UNLIKELY(m_displaced) ? displacedAddress() : HL().word);
case 7: case 7:
return a; return a;
default: default:
@@ -150,7 +150,7 @@ namespace EightBit {
} }
} }
void R(int r, uint8_t& a, uint8_t value) { void R(const int r, uint8_t& a, const uint8_t value) {
ASSUME(r >= 0); ASSUME(r >= 0);
ASSUME(r <= 7); ASSUME(r <= 7);
switch (r) { switch (r) {
@@ -173,7 +173,7 @@ namespace EightBit {
HL2().low = value; HL2().low = value;
break; break;
case 6: case 6:
BUS().write(LIKELY(!m_displaced) ? HL().word : displacedAddress(), value); BUS().write(UNLIKELY(m_displaced) ? displacedAddress() : HL().word, value);
break; break;
case 7: case 7:
a = value; a = value;
@@ -183,7 +183,7 @@ namespace EightBit {
} }
} }
uint8_t R2(int r, uint8_t a) { uint8_t R2(const int r, const uint8_t a) {
ASSUME(r >= 0); ASSUME(r >= 0);
ASSUME(r <= 7); ASSUME(r <= 7);
switch (r) { switch (r) {
@@ -208,7 +208,7 @@ namespace EightBit {
} }
} }
void R2(int r, uint8_t& a, uint8_t value) { void R2(const int r, uint8_t& a, const uint8_t value) {
ASSUME(r >= 0); ASSUME(r >= 0);
ASSUME(r <= 7); ASSUME(r <= 7);
switch (r) { switch (r) {
@@ -241,7 +241,7 @@ namespace EightBit {
} }
} }
register16_t& RP(int rp) { register16_t& RP(const int rp) {
ASSUME(rp >= 0); ASSUME(rp >= 0);
ASSUME(rp <= 3); ASSUME(rp <= 3);
switch (rp) { switch (rp) {
@@ -267,7 +267,7 @@ namespace EightBit {
return IY(); return IY();
} }
register16_t& RP2(int rp) { register16_t& RP2(const int rp) {
ASSUME(rp >= 0); ASSUME(rp >= 0);
ASSUME(rp <= 3); ASSUME(rp <= 3);
switch (rp) { switch (rp) {
@@ -284,28 +284,28 @@ namespace EightBit {
} }
} }
static void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) { static void adjustHalfCarryAdd(uint8_t& f, const uint8_t before, const uint8_t value, const int calculation) {
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation)); setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
} }
static void adjustHalfCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) { static void adjustHalfCarrySub(uint8_t& f, const uint8_t before, const uint8_t value, const int calculation) {
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation)); setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
} }
static void adjustOverflowAdd(uint8_t& f, uint8_t before, uint8_t value, uint8_t calculation) { static void adjustOverflowAdd(uint8_t& f, const uint8_t before, const uint8_t value, const uint8_t calculation) {
adjustOverflowAdd(f, before & SF, value & SF, calculation & SF); adjustOverflowAdd(f, before & SF, value & SF, calculation & SF);
} }
static void adjustOverflowAdd(uint8_t& f, int beforeNegative, int valueNegative, int afterNegative) { static void adjustOverflowAdd(uint8_t& f, const int beforeNegative, const int valueNegative, const int afterNegative) {
auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative); auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
setFlag(f, VF, overflow); setFlag(f, VF, overflow);
} }
static void adjustOverflowSub(uint8_t& f, uint8_t before, uint8_t value, uint8_t calculation) { static void adjustOverflowSub(uint8_t& f, const uint8_t before, const uint8_t value, const uint8_t calculation) {
adjustOverflowSub(f, before & SF, value & SF, calculation & SF); adjustOverflowSub(f, before & SF, value & SF, calculation & SF);
} }
static void adjustOverflowSub(uint8_t& f, int beforeNegative, int valueNegative, int afterNegative) { static void adjustOverflowSub(uint8_t& f, const int beforeNegative, const int valueNegative, const int afterNegative) {
auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative); auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
setFlag(f, VF, overflow); setFlag(f, VF, overflow);
} }

View File

@@ -73,7 +73,7 @@ void EightBit::Z80::decrement(uint8_t& f, uint8_t& operand) {
setFlag(f, VF, operand == Mask7); setFlag(f, VF, operand == Mask7);
} }
bool EightBit::Z80::jrConditionalFlag(uint8_t f, const int flag) { bool EightBit::Z80::jrConditionalFlag(const uint8_t f, const int flag) {
ASSUME(flag >= 0); ASSUME(flag >= 0);
ASSUME(flag <= 3); ASSUME(flag <= 3);
switch (flag) { switch (flag) {
@@ -90,7 +90,7 @@ bool EightBit::Z80::jrConditionalFlag(uint8_t f, const int flag) {
} }
} }
bool EightBit::Z80::jumpConditionalFlag(uint8_t f, const int flag) { bool EightBit::Z80::jumpConditionalFlag(const uint8_t f, const int flag) {
ASSUME(flag >= 0); ASSUME(flag >= 0);
ASSUME(flag <= 7); ASSUME(flag <= 7);
switch (flag) { switch (flag) {
@@ -125,7 +125,7 @@ void EightBit::Z80::reti() {
retn(); retn();
} }
bool EightBit::Z80::returnConditionalFlag(uint8_t f, const int flag) { bool EightBit::Z80::returnConditionalFlag(const uint8_t f, const int flag) {
ASSUME(flag >= 0); ASSUME(flag >= 0);
ASSUME(flag <= 7); ASSUME(flag <= 7);
switch (flag) { switch (flag) {
@@ -150,7 +150,7 @@ bool EightBit::Z80::returnConditionalFlag(uint8_t f, const int flag) {
} }
} }
bool EightBit::Z80::callConditionalFlag(uint8_t f, const int flag) { bool EightBit::Z80::callConditionalFlag(const uint8_t f, const int flag) {
ASSUME(flag >= 0); ASSUME(flag >= 0);
ASSUME(flag <= 7); ASSUME(flag <= 7);
switch (flag) { switch (flag) {
@@ -372,7 +372,7 @@ uint8_t EightBit::Z80::srl(uint8_t& f, uint8_t operand) {
return operand; return operand;
} }
uint8_t EightBit::Z80::bit(uint8_t& f, int n, uint8_t operand) { uint8_t EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) {
ASSUME(n >= 0); ASSUME(n >= 0);
ASSUME(n <= 7); ASSUME(n <= 7);
setFlag(f, HC); setFlag(f, HC);
@@ -383,13 +383,13 @@ uint8_t EightBit::Z80::bit(uint8_t& f, int n, uint8_t operand) {
return operand; return operand;
} }
uint8_t EightBit::Z80::res(int n, const uint8_t operand) { uint8_t EightBit::Z80::res(const int n, const uint8_t operand) {
ASSUME(n >= 0); ASSUME(n >= 0);
ASSUME(n <= 7); ASSUME(n <= 7);
return operand & ~(1 << n); return operand & ~(1 << n);
} }
uint8_t EightBit::Z80::set(int n, const uint8_t operand) { uint8_t EightBit::Z80::set(const int n, const uint8_t operand) {
ASSUME(n >= 0); ASSUME(n >= 0);
ASSUME(n <= 7); ASSUME(n <= 7);
return operand | (1 << n); return operand | (1 << n);
@@ -710,15 +710,15 @@ int EightBit::Z80::execute(const uint8_t opcode) {
auto& f = af.low; auto& f = af.low;
auto prefixed = m_prefixCB || m_prefixED; auto prefixed = m_prefixCB || m_prefixED;
if (LIKELY(!prefixed)) { if (UNLIKELY(prefixed)) {
executeOther(a, f, x, y, z, p, q);
} else {
if (m_prefixCB) if (m_prefixCB)
executeCB(a, f, x, y, z); executeCB(a, f, x, y, z);
else if (m_prefixED) else if (m_prefixED)
executeED(a, f, x, y, z, p, q); executeED(a, f, x, y, z, p, q);
else else
UNREACHABLE; UNREACHABLE;
} else {
executeOther(a, f, x, y, z, p, q);
} }
ASSUME(cycles() > 0); ASSUME(cycles() > 0);
@@ -764,21 +764,25 @@ void EightBit::Z80::executeCB(uint8_t& a, uint8_t& f, const int x, const int y,
UNREACHABLE; UNREACHABLE;
} }
adjustSZP<Z80>(f, operand); adjustSZP<Z80>(f, operand);
if (LIKELY(!m_displaced)) { if (UNLIKELY(m_displaced)) {
R(z, a, operand);
if (UNLIKELY(z == 6))
addCycles(7);
} else {
if (LIKELY(z != 6)) if (LIKELY(z != 6))
R2(z, a, operand); R2(z, a, operand);
BUS().write(operand); BUS().write(operand);
addCycles(15); addCycles(15);
} else {
R(z, a, operand);
if (UNLIKELY(z == 6))
addCycles(7);
} }
addCycles(8); addCycles(8);
break; break;
} case 1: // BIT y, r[z] } case 1: // BIT y, r[z]
addCycles(8); addCycles(8);
if (LIKELY(!m_displaced)) { if (UNLIKELY(m_displaced)) {
bit(f, y, BUS().read(displacedAddress()));
adjustXY<Z80>(f, MEMPTR().high);
addCycles(12);
} else {
const auto operand = bit(f, y, R(z, a)); const auto operand = bit(f, y, R(z, a));
if (UNLIKELY(z == 6)) { if (UNLIKELY(z == 6)) {
adjustXY<Z80>(f, MEMPTR().high); adjustXY<Z80>(f, MEMPTR().high);
@@ -786,38 +790,34 @@ void EightBit::Z80::executeCB(uint8_t& a, uint8_t& f, const int x, const int y,
} else { } else {
adjustXY<Z80>(f, operand); adjustXY<Z80>(f, operand);
} }
} else {
bit(f, y, BUS().read(displacedAddress()));
adjustXY<Z80>(f, MEMPTR().high);
addCycles(12);
} }
break; break;
case 2: // RES y, r[z] case 2: // RES y, r[z]
addCycles(8); addCycles(8);
if (LIKELY(!m_displaced)) { if (UNLIKELY(m_displaced)) {
R(z, a, res(y, R(z, a)));
if (UNLIKELY(z == 6))
addCycles(7);
} else {
auto operand = BUS().read(displacedAddress()); auto operand = BUS().read(displacedAddress());
operand = res(y, operand); operand = res(y, operand);
BUS().write(operand); BUS().write(operand);
R2(z, a, operand); R2(z, a, operand);
addCycles(15); addCycles(15);
} else {
R(z, a, res(y, R(z, a)));
if (UNLIKELY(z == 6))
addCycles(7);
} }
break; break;
case 3: // SET y, r[z] case 3: // SET y, r[z]
addCycles(8); addCycles(8);
if (LIKELY(!m_displaced)) { if (UNLIKELY(m_displaced)) {
R(z, a, set(y, R(z, a)));
if (UNLIKELY(z == 6))
addCycles(7);
} else {
auto operand = BUS().read(displacedAddress()); auto operand = BUS().read(displacedAddress());
operand = set(y, operand); operand = set(y, operand);
BUS().write(operand); BUS().write(operand);
R2(z, a, operand); R2(z, a, operand);
addCycles(15); addCycles(15);
} else {
R(z, a, set(y, R(z, a)));
if (UNLIKELY(z == 6))
addCycles(7);
} }
break; break;
default: default:
@@ -1222,22 +1222,24 @@ void EightBit::Z80::executeOther(uint8_t& a, uint8_t& f, const int x, const int
addCycles(4); addCycles(4);
break; break;
} case 5: { // 8-bit DEC } case 5: { // 8-bit DEC
if (UNLIKELY(m_displaced && (y == 6))) if (UNLIKELY(y == 6)) {
addCycles(7);
if (UNLIKELY(m_displaced))
fetchDisplacement(); fetchDisplacement();
}
auto operand = R(y, a); auto operand = R(y, a);
decrement(f, operand); decrement(f, operand);
R(y, a, operand); R(y, a, operand);
addCycles(4); addCycles(4);
if (UNLIKELY(y == 6))
addCycles(7);
break; break;
} case 6: // 8-bit load immediate } case 6: // 8-bit load immediate
if (UNLIKELY(m_displaced && (y == 6))) if (UNLIKELY(y == 6)) {
addCycles(3);
if (UNLIKELY(m_displaced))
fetchDisplacement(); fetchDisplacement();
}
R(y, a, fetchByte()); // LD r,n R(y, a, fetchByte()); // LD r,n
addCycles(7); addCycles(7);
if (UNLIKELY(y == 6))
addCycles(3);
break; break;
case 7: // Assorted operations on accumulator/flags case 7: // Assorted operations on accumulator/flags
switch (y) { switch (y) {
@@ -1315,8 +1317,11 @@ void EightBit::Z80::executeOther(uint8_t& a, uint8_t& f, const int x, const int
addCycles(4); addCycles(4);
break; break;
case 2: // Operate on accumulator and register/memory location case 2: // Operate on accumulator and register/memory location
if (UNLIKELY(m_displaced && (z == 6))) if (UNLIKELY(z == 6)) {
addCycles(3);
if (UNLIKELY(m_displaced))
fetchDisplacement(); fetchDisplacement();
}
switch (y) { switch (y) {
case 0: // ADD A,r case 0: // ADD A,r
add(f, a, R(z, a)); add(f, a, R(z, a));
@@ -1346,8 +1351,6 @@ void EightBit::Z80::executeOther(uint8_t& a, uint8_t& f, const int x, const int
UNREACHABLE; UNREACHABLE;
} }
addCycles(4); addCycles(4);
if (UNLIKELY(z == 6))
addCycles(3);
break; break;
case 3: case 3:
switch (z) { switch (z) {

View File

@@ -6,17 +6,17 @@
#include "Signal.h" #include "Signal.h"
namespace EightBit { namespace EightBit {
class InputOutput { class InputOutput final {
public: public:
InputOutput() = default; InputOutput() = default;
uint8_t read(uint8_t port) { return readInputPort(port); } uint8_t read(const uint8_t port) { return readInputPort(port); }
void write(uint8_t port, uint8_t value) { return writeOutputPort(port, value); } void write(const uint8_t port, const uint8_t value) { return writeOutputPort(port, value); }
uint8_t readInputPort(uint8_t port); uint8_t readInputPort(uint8_t port);
void writeInputPort(uint8_t port, uint8_t value) { m_input[port] = value; } void writeInputPort(const uint8_t port, const uint8_t value) { m_input[port] = value; }
uint8_t readOutputPort(uint8_t port) { return m_output[port]; } uint8_t readOutputPort(const uint8_t port) { return m_output[port]; }
void writeOutputPort(uint8_t port, uint8_t value); void writeOutputPort(uint8_t port, uint8_t value);
Signal<uint8_t> ReadingPort; Signal<uint8_t> ReadingPort;

View File

@@ -23,7 +23,7 @@ namespace EightBit {
opcode_decoded_t() {} opcode_decoded_t() {}
opcode_decoded_t(uint8_t opcode) { opcode_decoded_t(const uint8_t opcode) {
x = (opcode & 0b11000000) >> 6; // 0 - 3 x = (opcode & 0b11000000) >> 6; // 0 - 3
y = (opcode & 0b00111000) >> 3; // 0 - 7 y = (opcode & 0b00111000) >> 3; // 0 - 7
z = (opcode & 0b00000111); // 0 - 7 z = (opcode & 0b00000111); // 0 - 7
@@ -62,56 +62,56 @@ namespace EightBit {
virtual void reset() override; virtual void reset() override;
template<class T> static void adjustSign(uint8_t& f, uint8_t value) { template<class T> static void adjustSign(uint8_t& f, const uint8_t value) {
setFlag(f, T::SF, value & T::SF); setFlag(f, T::SF, value & T::SF);
} }
template<class T> static void adjustZero(uint8_t& f, uint8_t value) { template<class T> static void adjustZero(uint8_t& f, const uint8_t value) {
clearFlag(f, T::ZF, value); clearFlag(f, T::ZF, value);
} }
template<class T> static void adjustParity(uint8_t& f, uint8_t value) { template<class T> static void adjustParity(uint8_t& f, const uint8_t value) {
clearFlag(f, T::PF, PARITY(value)); clearFlag(f, T::PF, PARITY(value));
} }
template<class T> static void adjustSZ(uint8_t& f, uint8_t value) { template<class T> static void adjustSZ(uint8_t& f, const uint8_t value) {
adjustSign<T>(f, value); adjustSign<T>(f, value);
adjustZero<T>(f, value); adjustZero<T>(f, value);
} }
template<class T> static void adjustSZP(uint8_t& f, uint8_t value) { template<class T> static void adjustSZP(uint8_t& f, const uint8_t value) {
adjustSZ<T>(f, value); adjustSZ<T>(f, value);
adjustParity<T>(f, value); adjustParity<T>(f, value);
} }
template<class T> static void adjustXY(uint8_t& f, uint8_t value) { template<class T> static void adjustXY(uint8_t& f, const uint8_t value) {
setFlag(f, T::XF, value & T::XF); setFlag(f, T::XF, value & T::XF);
setFlag(f, T::YF, value & T::YF); setFlag(f, T::YF, value & T::YF);
} }
template<class T> static void adjustSZPXY(uint8_t& f, uint8_t value) { template<class T> static void adjustSZPXY(uint8_t& f, const uint8_t value) {
adjustSZP<T>(f, value); adjustSZP<T>(f, value);
adjustXY<T>(f, value); adjustXY<T>(f, value);
} }
template<class T> static void adjustSZXY(uint8_t& f, uint8_t value) { template<class T> static void adjustSZXY(uint8_t& f, const uint8_t value) {
adjustSZ<T>(f, value); adjustSZ<T>(f, value);
adjustXY<T>(f, value); adjustXY<T>(f, value);
} }
// //
static int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) { static int buildHalfCarryIndex(const uint8_t before, const uint8_t value, const int calculation) {
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3); return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
} }
static bool calculateHalfCarryAdd(uint8_t before, uint8_t value, int calculation) { static bool calculateHalfCarryAdd(const uint8_t before, const uint8_t value, const int calculation) {
static std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } }; static std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
const auto index = buildHalfCarryIndex(before, value, calculation); const auto index = buildHalfCarryIndex(before, value, calculation);
return m_halfCarryTableAdd[index & Mask3]; return m_halfCarryTableAdd[index & Mask3];
} }
static bool calculateHalfCarrySub(uint8_t before, uint8_t value, int calculation) { static bool calculateHalfCarrySub(const uint8_t before, const uint8_t value, const int calculation) {
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } }; std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
const auto index = buildHalfCarryIndex(before, value, calculation); const auto index = buildHalfCarryIndex(before, value, calculation);
return m_halfCarryTableSub[index & Mask3]; return m_halfCarryTableSub[index & Mask3];
@@ -127,27 +127,27 @@ namespace EightBit {
// //
void restart(uint8_t address) { void restart(const uint8_t address) {
MEMPTR().low = address; MEMPTR().low = address;
MEMPTR().high = 0; MEMPTR().high = 0;
call(MEMPTR()); call(MEMPTR());
} }
bool callConditional(int condition) { bool callConditional(const int condition) {
MEMPTR() = fetchWord(); MEMPTR() = fetchWord();
if (condition) if (condition)
call(MEMPTR()); call(MEMPTR());
return condition != 0; return condition != 0;
} }
bool jumpConditional(int conditional) { bool jumpConditional(const int conditional) {
MEMPTR() = fetchWord(); MEMPTR() = fetchWord();
if (conditional) if (conditional)
jump(MEMPTR()); jump(MEMPTR());
return conditional != 0; return conditional != 0;
} }
bool returnConditional(int condition) { bool returnConditional(const int condition) {
if (condition) { if (condition) {
ret(); ret();
MEMPTR() = PC(); MEMPTR() = PC();
@@ -155,12 +155,12 @@ namespace EightBit {
return condition != 0; return condition != 0;
} }
void jr(int8_t offset) { void jr(const int8_t offset) {
MEMPTR().word = PC().word + offset; MEMPTR().word = PC().word + offset;
jump(MEMPTR()); jump(MEMPTR());
} }
bool jrConditional(int conditional) { bool jrConditional(const int conditional) {
const auto offset = fetchByte(); const auto offset = fetchByte();
if (conditional) if (conditional)
jr(offset); jr(offset);

View File

@@ -11,23 +11,23 @@ namespace EightBit {
static int load(std::ifstream& file, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1); static int load(std::ifstream& file, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
static int load(const std::string& path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1); static int load(const std::string& path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
Memory(size_t size = 0) Memory(const size_t size = 0)
: m_bytes(size) { : m_bytes(size) {
} }
size_t size() const { return m_bytes.size(); } size_t size() const { return m_bytes.size(); }
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) { int load(std::ifstream& file, const int writeOffset = 0, const int readOffset = 0, const int limit = -1) {
const auto maximumSize = (int)m_bytes.size() - writeOffset; const auto maximumSize = (int)m_bytes.size() - writeOffset;
return load(file, m_bytes, writeOffset, readOffset, limit, maximumSize); return load(file, m_bytes, writeOffset, readOffset, limit, maximumSize);
} }
int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) { int load(const std::string& path, const int writeOffset = 0, const int readOffset = 0, const int limit = -1) {
const auto maximumSize = (int)m_bytes.size() - writeOffset; const auto maximumSize = (int)m_bytes.size() - writeOffset;
return load(path, m_bytes, writeOffset, readOffset, limit, maximumSize); return load(path, m_bytes, writeOffset, readOffset, limit, maximumSize);
} }
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) { int load(const std::vector<uint8_t>& bytes, const int writeOffset = 0, const int readOffset = 0, int limit = -1) {
if (limit < 0) if (limit < 0)
limit = (int)bytes.size() - readOffset; limit = (int)bytes.size() - readOffset;
std::copy(bytes.cbegin() + readOffset, bytes.cbegin() + limit, m_bytes.begin() + writeOffset); std::copy(bytes.cbegin() + readOffset, bytes.cbegin() + limit, m_bytes.begin() + writeOffset);
@@ -37,11 +37,11 @@ namespace EightBit {
protected: protected:
std::vector<uint8_t>& BYTES() { return m_bytes; } std::vector<uint8_t>& BYTES() { return m_bytes; }
uint8_t read(uint16_t address) const { uint8_t read(const uint16_t address) const {
return m_bytes[address]; return m_bytes[address];
} }
void write(uint16_t address, uint8_t value) { void write(const uint16_t address, const uint8_t value) {
m_bytes[address] = value; m_bytes[address] = value;
} }

View File

@@ -53,16 +53,16 @@ namespace EightBit {
Low, High Low, High
}; };
static bool raised(PinLevel line) { return line == High; } static bool raised(const PinLevel line) { return line == High; }
static void raise(PinLevel& line) { line = High; } static void raise(PinLevel& line) { line = High; }
static bool lowered(PinLevel line) { return line == Low; } static bool lowered(const PinLevel line) { return line == Low; }
static void lower(PinLevel& line) { line = Low; } static void lower(PinLevel& line) { line = Low; }
static int highNibble(int value) { return value >> 4; } static int highNibble(const int value) { return value >> 4; }
static int lowNibble(int value) { return value & Mask4; } static int lowNibble(const int value) { return value & Mask4; }
static int promoteNibble(int value) { return value << 4; } static int promoteNibble(const int value) { return value << 4; }
static int demoteNibble(int value) { return highNibble(value); } static int demoteNibble(const int value) { return highNibble(value); }
Bus& BUS() { return m_bus; } Bus& BUS() { return m_bus; }
@@ -85,16 +85,16 @@ namespace EightBit {
virtual int execute(uint8_t opcode) = 0; virtual int execute(uint8_t opcode) = 0;
protected: protected:
static void clearFlag(uint8_t& f, int flag) { f &= ~flag; } static void clearFlag(uint8_t& f, const int flag) { f &= ~flag; }
static void setFlag(uint8_t& f, int flag) { f |= flag; } static void setFlag(uint8_t& f, const int flag) { f |= flag; }
static void setFlag(uint8_t& f, int flag, int condition) { setFlag(f, flag, condition != 0); } static void setFlag(uint8_t& f, const int flag, const int condition) { setFlag(f, flag, condition != 0); }
static void setFlag(uint8_t& f, int flag, uint32_t condition) { setFlag(f, flag, condition != 0); } static void setFlag(uint8_t& f, const int flag, const uint32_t condition) { setFlag(f, flag, condition != 0); }
static void setFlag(uint8_t& f, int flag, bool condition) { condition ? setFlag(f, flag) : clearFlag(f, flag); } static void setFlag(uint8_t& f, const int flag, const bool condition) { condition ? setFlag(f, flag) : clearFlag(f, flag); }
static void clearFlag(uint8_t& f, int flag, int condition) { clearFlag(f, flag, condition != 0); } static void clearFlag(uint8_t& f, const int flag, const int condition) { clearFlag(f, flag, condition != 0); }
static void clearFlag(uint8_t& f, int flag, uint32_t condition) { clearFlag(f, flag, condition != 0); } static void clearFlag(uint8_t& f, const int flag, const uint32_t condition) { clearFlag(f, flag, condition != 0); }
static void clearFlag(uint8_t& f, int flag, bool condition) { condition ? clearFlag(f, flag) : setFlag(f, flag); } static void clearFlag(uint8_t& f, const int flag, const bool condition) { condition ? clearFlag(f, flag) : setFlag(f, flag); }
Processor(Bus& memory); Processor(Bus& memory);
virtual ~Processor() = default; virtual ~Processor() = default;
@@ -119,7 +119,7 @@ namespace EightBit {
virtual void push(uint8_t value) = 0; virtual void push(uint8_t value) = 0;
virtual uint8_t pop() = 0; virtual uint8_t pop() = 0;
void pushWord(register16_t value) { void pushWord(const register16_t value) {
push(value.high); push(value.high);
push(value.low); push(value.low);
} }
@@ -131,11 +131,11 @@ namespace EightBit {
return returned; return returned;
} }
void jump(register16_t destination) { void jump(const register16_t destination) {
PC() = destination; PC() = destination;
} }
void call(register16_t destination) { void call(const register16_t destination) {
pushWord(PC()); pushWord(PC());
jump(destination); jump(destination);
} }
@@ -146,7 +146,7 @@ namespace EightBit {
int cycles() const { return m_cycles; } int cycles() const { return m_cycles; }
void resetCycles() { m_cycles = 0; } void resetCycles() { m_cycles = 0; }
void addCycles(int extra) { m_cycles += extra; } void addCycles(const int extra) { m_cycles += extra; }
void addCycle() { ++m_cycles; } void addCycle() { ++m_cycles; }
private: private:

View File

@@ -6,19 +6,19 @@
namespace EightBit { namespace EightBit {
class Ram : public Memory { class Ram : public Memory {
public: public:
Ram(size_t size = 0) Ram(const size_t size = 0)
: Memory(size) { : Memory(size) {
} }
uint8_t peek(uint16_t address) const { uint8_t peek(const uint16_t address) const {
return read(address); return read(address);
} }
void poke(uint16_t address, uint8_t value) { void poke(const uint16_t address, const uint8_t value) {
write(address, value); write(address, value);
} }
uint8_t& reference(uint16_t address) { uint8_t& reference(const uint16_t address) {
return BYTES()[address]; return BYTES()[address];
} }
}; };

View File

@@ -6,15 +6,15 @@
namespace EightBit { namespace EightBit {
class Rom : public Memory { class Rom : public Memory {
public: public:
Rom(size_t size = 0) Rom(const size_t size = 0)
: Memory(size) { : Memory(size) {
} }
uint8_t peek(uint16_t address) const { uint8_t peek(const uint16_t address) const {
return read(address); return read(address);
} }
uint8_t& reference(uint16_t address) { uint8_t& reference(const uint16_t address) {
return BYTES()[address]; return BYTES()[address];
} }
}; };

View File

@@ -4,7 +4,7 @@
#include <functional> #include <functional>
namespace EightBit { namespace EightBit {
template<class T> class Signal { template<class T> class Signal final {
private: private:
typedef std::function<void(const T&)> delegate_t; typedef std::function<void(const T&)> delegate_t;
typedef std::vector<delegate_t> delegates_t; typedef std::vector<delegate_t> delegates_t;
@@ -12,7 +12,7 @@ namespace EightBit {
delegates_t m_delegates; delegates_t m_delegates;
public: public:
void connect(delegate_t functor) { void connect(const delegate_t functor) {
m_delegates.push_back(functor); m_delegates.push_back(functor);
} }

View File

@@ -18,11 +18,7 @@ namespace EightBit {
template<class ConfigurationT, class BoardT> class TestHarness { template<class ConfigurationT, class BoardT> class TestHarness {
public: public:
TestHarness(const ConfigurationT& configuration) TestHarness(const ConfigurationT& configuration)
: m_board(configuration), : m_board(configuration) {
m_totalCycles(0),
m_instructions(0),
m_startHostCycles(0),
m_finishHostCycles(0) {
} }
~TestHarness() { ~TestHarness() {
@@ -81,12 +77,12 @@ namespace EightBit {
private: private:
BoardT m_board; BoardT m_board;
long long m_totalCycles; long long m_totalCycles = 0;
long long m_instructions; long long m_instructions = 0;
std::chrono::steady_clock::time_point m_startTime; std::chrono::steady_clock::time_point m_startTime;
std::chrono::steady_clock::time_point m_finishTime; std::chrono::steady_clock::time_point m_finishTime;
uint64_t m_startHostCycles; uint64_t m_startHostCycles = 0;
uint64_t m_finishHostCycles; uint64_t m_finishHostCycles = 0;
static std::chrono::steady_clock::time_point now() { static std::chrono::steady_clock::time_point now() {
return std::chrono::steady_clock::now(); return std::chrono::steady_clock::now();

View File

@@ -11,7 +11,7 @@ uint8_t& EightBit::Bus::DATA() {
return *m_data; return *m_data;
} }
uint8_t& EightBit::Bus::placeDATA(uint8_t value) { uint8_t& EightBit::Bus::placeDATA(const uint8_t value) {
m_temporary = value; m_temporary = value;
m_data = &m_temporary; m_data = &m_temporary;
return DATA(); return DATA();
@@ -22,17 +22,17 @@ uint8_t& EightBit::Bus::referenceDATA(uint8_t& value) {
return DATA(); return DATA();
} }
uint8_t EightBit::Bus::peek(uint16_t address) { uint8_t EightBit::Bus::peek(const uint16_t address) {
bool rom; bool rom;
return reference(address, rom); return reference(address, rom);
} }
void EightBit::Bus::poke(uint16_t address, uint8_t value) { void EightBit::Bus::poke(const uint16_t address, const uint8_t value) {
bool rom; bool rom;
reference(address, rom) = value; reference(address, rom) = value;
} }
uint16_t EightBit::Bus::peekWord(uint16_t address) { uint16_t EightBit::Bus::peekWord(const uint16_t address) {
register16_t returned; register16_t returned;
returned.low = peek(address); returned.low = peek(address);
returned.high = peek(address + 1); returned.high = peek(address + 1);
@@ -46,28 +46,28 @@ uint8_t EightBit::Bus::read() {
return returned; return returned;
} }
uint8_t EightBit::Bus::read(uint16_t offset) { uint8_t EightBit::Bus::read(const uint16_t offset) {
ADDRESS().word = offset; ADDRESS().word = offset;
return read(); return read();
} }
uint8_t EightBit::Bus::read(register16_t address) { uint8_t EightBit::Bus::read(const register16_t address) {
ADDRESS() = address; ADDRESS() = address;
return read(); return read();
} }
void EightBit::Bus::write(uint8_t value) { void EightBit::Bus::write(const uint8_t value) {
WritingByte.fire(ADDRESS().word); WritingByte.fire(ADDRESS().word);
reference() = value; reference() = value;
WrittenByte.fire(ADDRESS().word); WrittenByte.fire(ADDRESS().word);
} }
void EightBit::Bus::write(uint16_t offset, uint8_t value) { void EightBit::Bus::write(const uint16_t offset, const uint8_t value) {
ADDRESS().word = offset; ADDRESS().word = offset;
write(value); write(value);
} }
void EightBit::Bus::write(register16_t address, uint8_t value) { void EightBit::Bus::write(const register16_t address, const uint8_t value) {
ADDRESS() = address; ADDRESS() = address;
write(value); write(value);
} }
@@ -75,5 +75,5 @@ void EightBit::Bus::write(register16_t address, uint8_t value) {
uint8_t& EightBit::Bus::reference() { uint8_t& EightBit::Bus::reference() {
bool rom; bool rom;
auto& value = reference(ADDRESS().word, rom); auto& value = reference(ADDRESS().word, rom);
return LIKELY(!rom) ? referenceDATA(value) : placeDATA(value); return rom ? placeDATA(value) : referenceDATA(value);
} }

View File

@@ -1,31 +1,31 @@
#include "stdafx.h" #include "stdafx.h"
#include "InputOutput.h" #include "InputOutput.h"
uint8_t EightBit::InputOutput::readInputPort(uint8_t port) { uint8_t EightBit::InputOutput::readInputPort(const uint8_t port) {
OnReadingPort(port); OnReadingPort(port);
const auto value = m_input[port]; const auto value = m_input[port];
OnReadPort(port); OnReadPort(port);
return value; return value;
} }
void EightBit::InputOutput::writeOutputPort(uint8_t port, uint8_t value) { void EightBit::InputOutput::writeOutputPort(const uint8_t port, const uint8_t value) {
OnWritingPort(port); OnWritingPort(port);
m_output[port] = value; m_output[port] = value;
OnWrittenPort(port); OnWrittenPort(port);
} }
void EightBit::InputOutput::OnReadingPort(uint8_t port) { void EightBit::InputOutput::OnReadingPort(const uint8_t port) {
ReadingPort.fire(port); ReadingPort.fire(port);
} }
void EightBit::InputOutput::OnReadPort(uint8_t port) { void EightBit::InputOutput::OnReadPort(const uint8_t port) {
ReadPort.fire(port); ReadPort.fire(port);
} }
void EightBit::InputOutput::OnWritingPort(uint8_t port) { void EightBit::InputOutput::OnWritingPort(const uint8_t port) {
WritingPort.fire(port); WritingPort.fire(port);
} }
void EightBit::InputOutput::OnWrittenPort(uint8_t port) { void EightBit::InputOutput::OnWrittenPort(const uint8_t port) {
WrittenPort.fire(port); WrittenPort.fire(port);
} }

View File

@@ -12,7 +12,7 @@ void EightBit::IntelProcessor::reset() {
SP().word = AF().word = BC().word = DE().word = HL().word = Mask16; SP().word = AF().word = BC().word = DE().word = HL().word = Mask16;
} }
void EightBit::IntelProcessor::push(uint8_t value) { void EightBit::IntelProcessor::push(const uint8_t value) {
BUS().write(--SP().word, value); BUS().write(--SP().word, value);
} }
@@ -27,7 +27,7 @@ EightBit::register16_t EightBit::IntelProcessor::getWord() {
return returned; return returned;
} }
void EightBit::IntelProcessor::setWord(register16_t value) { void EightBit::IntelProcessor::setWord(const register16_t value) {
BUS().write(MEMPTR().word++, value.low); BUS().write(MEMPTR().word++, value.low);
BUS().write(++BUS().ADDRESS().word, value.high); BUS().write(++BUS().ADDRESS().word, value.high);
} }

View File

@@ -14,7 +14,7 @@ void EightBit::Processor::reset() {
PC().word = 0; PC().word = 0;
} }
int EightBit::Processor::run(int limit) { int EightBit::Processor::run(const int limit) {
int current = 0; int current = 0;
while (LIKELY(powered()) && current < limit) { while (LIKELY(powered()) && current < limit) {
current += singleStep(); current += singleStep();