mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-22 09:30:32 +00:00
Remove some "tricksy" code from the Z80 emulator chain.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
4b4f6b1a49
commit
9de0f597f6
@ -19,7 +19,7 @@ namespace EightBit {
|
||||
bool high : 1;
|
||||
uint8_t variable : 7;
|
||||
|
||||
refresh_t(uint8_t value)
|
||||
refresh_t(const uint8_t value)
|
||||
: high((value & Bit7) != 0),
|
||||
variable(value & Mask7)
|
||||
{ }
|
||||
@ -125,7 +125,7 @@ namespace EightBit {
|
||||
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 <= 7);
|
||||
switch (r) {
|
||||
@ -142,7 +142,7 @@ namespace EightBit {
|
||||
case 5:
|
||||
return HL2().low;
|
||||
case 6:
|
||||
return BUS().read(LIKELY(!m_displaced) ? HL().word : displacedAddress());
|
||||
return BUS().read(UNLIKELY(m_displaced) ? displacedAddress() : HL().word);
|
||||
case 7:
|
||||
return a;
|
||||
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 <= 7);
|
||||
switch (r) {
|
||||
@ -173,7 +173,7 @@ namespace EightBit {
|
||||
HL2().low = value;
|
||||
break;
|
||||
case 6:
|
||||
BUS().write(LIKELY(!m_displaced) ? HL().word : displacedAddress(), value);
|
||||
BUS().write(UNLIKELY(m_displaced) ? displacedAddress() : HL().word, value);
|
||||
break;
|
||||
case 7:
|
||||
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 <= 7);
|
||||
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 <= 7);
|
||||
switch (r) {
|
||||
@ -241,7 +241,7 @@ namespace EightBit {
|
||||
}
|
||||
}
|
||||
|
||||
register16_t& RP(int rp) {
|
||||
register16_t& RP(const int rp) {
|
||||
ASSUME(rp >= 0);
|
||||
ASSUME(rp <= 3);
|
||||
switch (rp) {
|
||||
@ -267,7 +267,7 @@ namespace EightBit {
|
||||
return IY();
|
||||
}
|
||||
|
||||
register16_t& RP2(int rp) {
|
||||
register16_t& RP2(const int rp) {
|
||||
ASSUME(rp >= 0);
|
||||
ASSUME(rp <= 3);
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
setFlag(f, VF, overflow);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ void EightBit::Z80::decrement(uint8_t& f, uint8_t& operand) {
|
||||
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 <= 3);
|
||||
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 <= 7);
|
||||
switch (flag) {
|
||||
@ -125,7 +125,7 @@ void EightBit::Z80::reti() {
|
||||
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 <= 7);
|
||||
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 <= 7);
|
||||
switch (flag) {
|
||||
@ -372,7 +372,7 @@ uint8_t EightBit::Z80::srl(uint8_t& f, uint8_t 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 <= 7);
|
||||
setFlag(f, HC);
|
||||
@ -383,13 +383,13 @@ uint8_t EightBit::Z80::bit(uint8_t& f, int n, uint8_t 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 <= 7);
|
||||
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 <= 7);
|
||||
return operand | (1 << n);
|
||||
@ -710,15 +710,15 @@ int EightBit::Z80::execute(const uint8_t opcode) {
|
||||
auto& f = af.low;
|
||||
|
||||
auto prefixed = m_prefixCB || m_prefixED;
|
||||
if (LIKELY(!prefixed)) {
|
||||
executeOther(a, f, x, y, z, p, q);
|
||||
} else {
|
||||
if (UNLIKELY(prefixed)) {
|
||||
if (m_prefixCB)
|
||||
executeCB(a, f, x, y, z);
|
||||
else if (m_prefixED)
|
||||
executeED(a, f, x, y, z, p, q);
|
||||
else
|
||||
UNREACHABLE;
|
||||
} else {
|
||||
executeOther(a, f, x, y, z, p, q);
|
||||
}
|
||||
|
||||
ASSUME(cycles() > 0);
|
||||
@ -764,21 +764,25 @@ void EightBit::Z80::executeCB(uint8_t& a, uint8_t& f, const int x, const int y,
|
||||
UNREACHABLE;
|
||||
}
|
||||
adjustSZP<Z80>(f, operand);
|
||||
if (LIKELY(!m_displaced)) {
|
||||
R(z, a, operand);
|
||||
if (UNLIKELY(z == 6))
|
||||
addCycles(7);
|
||||
} else {
|
||||
if (UNLIKELY(m_displaced)) {
|
||||
if (LIKELY(z != 6))
|
||||
R2(z, a, operand);
|
||||
BUS().write(operand);
|
||||
addCycles(15);
|
||||
} else {
|
||||
R(z, a, operand);
|
||||
if (UNLIKELY(z == 6))
|
||||
addCycles(7);
|
||||
}
|
||||
addCycles(8);
|
||||
break;
|
||||
} case 1: // BIT y, r[z]
|
||||
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));
|
||||
if (UNLIKELY(z == 6)) {
|
||||
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 {
|
||||
adjustXY<Z80>(f, operand);
|
||||
}
|
||||
} else {
|
||||
bit(f, y, BUS().read(displacedAddress()));
|
||||
adjustXY<Z80>(f, MEMPTR().high);
|
||||
addCycles(12);
|
||||
}
|
||||
break;
|
||||
case 2: // RES y, r[z]
|
||||
addCycles(8);
|
||||
if (LIKELY(!m_displaced)) {
|
||||
R(z, a, res(y, R(z, a)));
|
||||
if (UNLIKELY(z == 6))
|
||||
addCycles(7);
|
||||
} else {
|
||||
if (UNLIKELY(m_displaced)) {
|
||||
auto operand = BUS().read(displacedAddress());
|
||||
operand = res(y, operand);
|
||||
BUS().write(operand);
|
||||
R2(z, a, operand);
|
||||
addCycles(15);
|
||||
} else {
|
||||
R(z, a, res(y, R(z, a)));
|
||||
if (UNLIKELY(z == 6))
|
||||
addCycles(7);
|
||||
}
|
||||
break;
|
||||
case 3: // SET y, r[z]
|
||||
addCycles(8);
|
||||
if (LIKELY(!m_displaced)) {
|
||||
R(z, a, set(y, R(z, a)));
|
||||
if (UNLIKELY(z == 6))
|
||||
addCycles(7);
|
||||
} else {
|
||||
if (UNLIKELY(m_displaced)) {
|
||||
auto operand = BUS().read(displacedAddress());
|
||||
operand = set(y, operand);
|
||||
BUS().write(operand);
|
||||
R2(z, a, operand);
|
||||
addCycles(15);
|
||||
} else {
|
||||
R(z, a, set(y, R(z, a)));
|
||||
if (UNLIKELY(z == 6))
|
||||
addCycles(7);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1222,22 +1222,24 @@ void EightBit::Z80::executeOther(uint8_t& a, uint8_t& f, const int x, const int
|
||||
addCycles(4);
|
||||
break;
|
||||
} case 5: { // 8-bit DEC
|
||||
if (UNLIKELY(m_displaced && (y == 6)))
|
||||
fetchDisplacement();
|
||||
if (UNLIKELY(y == 6)) {
|
||||
addCycles(7);
|
||||
if (UNLIKELY(m_displaced))
|
||||
fetchDisplacement();
|
||||
}
|
||||
auto operand = R(y, a);
|
||||
decrement(f, operand);
|
||||
R(y, a, operand);
|
||||
addCycles(4);
|
||||
if (UNLIKELY(y == 6))
|
||||
addCycles(7);
|
||||
break;
|
||||
} case 6: // 8-bit load immediate
|
||||
if (UNLIKELY(m_displaced && (y == 6)))
|
||||
fetchDisplacement();
|
||||
if (UNLIKELY(y == 6)) {
|
||||
addCycles(3);
|
||||
if (UNLIKELY(m_displaced))
|
||||
fetchDisplacement();
|
||||
}
|
||||
R(y, a, fetchByte()); // LD r,n
|
||||
addCycles(7);
|
||||
if (UNLIKELY(y == 6))
|
||||
addCycles(3);
|
||||
break;
|
||||
case 7: // Assorted operations on accumulator/flags
|
||||
switch (y) {
|
||||
@ -1315,8 +1317,11 @@ void EightBit::Z80::executeOther(uint8_t& a, uint8_t& f, const int x, const int
|
||||
addCycles(4);
|
||||
break;
|
||||
case 2: // Operate on accumulator and register/memory location
|
||||
if (UNLIKELY(m_displaced && (z == 6)))
|
||||
fetchDisplacement();
|
||||
if (UNLIKELY(z == 6)) {
|
||||
addCycles(3);
|
||||
if (UNLIKELY(m_displaced))
|
||||
fetchDisplacement();
|
||||
}
|
||||
switch (y) {
|
||||
case 0: // ADD A,r
|
||||
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;
|
||||
}
|
||||
addCycles(4);
|
||||
if (UNLIKELY(z == 6))
|
||||
addCycles(3);
|
||||
break;
|
||||
case 3:
|
||||
switch (z) {
|
||||
|
@ -6,17 +6,17 @@
|
||||
#include "Signal.h"
|
||||
|
||||
namespace EightBit {
|
||||
class InputOutput {
|
||||
class InputOutput final {
|
||||
public:
|
||||
InputOutput() = default;
|
||||
|
||||
uint8_t read(uint8_t port) { return readInputPort(port); }
|
||||
void write(uint8_t port, uint8_t value) { return writeOutputPort(port, value); }
|
||||
uint8_t read(const uint8_t port) { return readInputPort(port); }
|
||||
void write(const uint8_t port, const uint8_t value) { return writeOutputPort(port, value); }
|
||||
|
||||
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);
|
||||
|
||||
Signal<uint8_t> ReadingPort;
|
||||
|
@ -23,7 +23,7 @@ namespace EightBit {
|
||||
|
||||
opcode_decoded_t() {}
|
||||
|
||||
opcode_decoded_t(uint8_t opcode) {
|
||||
opcode_decoded_t(const uint8_t opcode) {
|
||||
x = (opcode & 0b11000000) >> 6; // 0 - 3
|
||||
y = (opcode & 0b00111000) >> 3; // 0 - 7
|
||||
z = (opcode & 0b00000111); // 0 - 7
|
||||
@ -62,56 +62,56 @@ namespace EightBit {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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::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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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 } };
|
||||
const auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
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 } };
|
||||
const auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
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().high = 0;
|
||||
call(MEMPTR());
|
||||
}
|
||||
|
||||
bool callConditional(int condition) {
|
||||
bool callConditional(const int condition) {
|
||||
MEMPTR() = fetchWord();
|
||||
if (condition)
|
||||
call(MEMPTR());
|
||||
return condition != 0;
|
||||
}
|
||||
|
||||
bool jumpConditional(int conditional) {
|
||||
bool jumpConditional(const int conditional) {
|
||||
MEMPTR() = fetchWord();
|
||||
if (conditional)
|
||||
jump(MEMPTR());
|
||||
return conditional != 0;
|
||||
}
|
||||
|
||||
bool returnConditional(int condition) {
|
||||
bool returnConditional(const int condition) {
|
||||
if (condition) {
|
||||
ret();
|
||||
MEMPTR() = PC();
|
||||
@ -155,12 +155,12 @@ namespace EightBit {
|
||||
return condition != 0;
|
||||
}
|
||||
|
||||
void jr(int8_t offset) {
|
||||
void jr(const int8_t offset) {
|
||||
MEMPTR().word = PC().word + offset;
|
||||
jump(MEMPTR());
|
||||
}
|
||||
|
||||
bool jrConditional(int conditional) {
|
||||
bool jrConditional(const int conditional) {
|
||||
const auto offset = fetchByte();
|
||||
if (conditional)
|
||||
jr(offset);
|
||||
|
12
inc/Memory.h
12
inc/Memory.h
@ -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(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) {
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
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)
|
||||
limit = (int)bytes.size() - readOffset;
|
||||
std::copy(bytes.cbegin() + readOffset, bytes.cbegin() + limit, m_bytes.begin() + writeOffset);
|
||||
@ -37,11 +37,11 @@ namespace EightBit {
|
||||
protected:
|
||||
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];
|
||||
}
|
||||
|
||||
void write(uint16_t address, uint8_t value) {
|
||||
void write(const uint16_t address, const uint8_t value) {
|
||||
m_bytes[address] = value;
|
||||
}
|
||||
|
||||
|
@ -53,16 +53,16 @@ namespace EightBit {
|
||||
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 bool lowered(PinLevel line) { return line == Low; }
|
||||
static bool lowered(const PinLevel line) { return line == Low; }
|
||||
static void lower(PinLevel& line) { line = Low; }
|
||||
|
||||
static int highNibble(int value) { return value >> 4; }
|
||||
static int lowNibble(int value) { return value & Mask4; }
|
||||
static int highNibble(const int value) { return value >> 4; }
|
||||
static int lowNibble(const int value) { return value & Mask4; }
|
||||
|
||||
static int promoteNibble(int value) { return value << 4; }
|
||||
static int demoteNibble(int value) { return highNibble(value); }
|
||||
static int promoteNibble(const int value) { return value << 4; }
|
||||
static int demoteNibble(const int value) { return highNibble(value); }
|
||||
|
||||
Bus& BUS() { return m_bus; }
|
||||
|
||||
@ -85,16 +85,16 @@ namespace EightBit {
|
||||
virtual int execute(uint8_t opcode) = 0;
|
||||
|
||||
protected:
|
||||
static void clearFlag(uint8_t& f, int flag) { f &= ~flag; }
|
||||
static void setFlag(uint8_t& f, int flag) { f |= flag; }
|
||||
static void clearFlag(uint8_t& f, const 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, int flag, 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 int 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, 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, int flag, 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 int 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, const int flag, const bool condition) { condition ? clearFlag(f, flag) : setFlag(f, flag); }
|
||||
|
||||
Processor(Bus& memory);
|
||||
virtual ~Processor() = default;
|
||||
@ -119,7 +119,7 @@ namespace EightBit {
|
||||
virtual void push(uint8_t value) = 0;
|
||||
virtual uint8_t pop() = 0;
|
||||
|
||||
void pushWord(register16_t value) {
|
||||
void pushWord(const register16_t value) {
|
||||
push(value.high);
|
||||
push(value.low);
|
||||
}
|
||||
@ -131,11 +131,11 @@ namespace EightBit {
|
||||
return returned;
|
||||
}
|
||||
|
||||
void jump(register16_t destination) {
|
||||
void jump(const register16_t destination) {
|
||||
PC() = destination;
|
||||
}
|
||||
|
||||
void call(register16_t destination) {
|
||||
void call(const register16_t destination) {
|
||||
pushWord(PC());
|
||||
jump(destination);
|
||||
}
|
||||
@ -146,7 +146,7 @@ namespace EightBit {
|
||||
|
||||
int cycles() const { return m_cycles; }
|
||||
void resetCycles() { m_cycles = 0; }
|
||||
void addCycles(int extra) { m_cycles += extra; }
|
||||
void addCycles(const int extra) { m_cycles += extra; }
|
||||
void addCycle() { ++m_cycles; }
|
||||
|
||||
private:
|
||||
|
@ -6,19 +6,19 @@
|
||||
namespace EightBit {
|
||||
class Ram : public Memory {
|
||||
public:
|
||||
Ram(size_t size = 0)
|
||||
Ram(const size_t size = 0)
|
||||
: Memory(size) {
|
||||
}
|
||||
|
||||
uint8_t peek(uint16_t address) const {
|
||||
uint8_t peek(const uint16_t address) const {
|
||||
return read(address);
|
||||
}
|
||||
|
||||
void poke(uint16_t address, uint8_t value) {
|
||||
void poke(const uint16_t address, const uint8_t value) {
|
||||
write(address, value);
|
||||
}
|
||||
|
||||
uint8_t& reference(uint16_t address) {
|
||||
uint8_t& reference(const uint16_t address) {
|
||||
return BYTES()[address];
|
||||
}
|
||||
};
|
||||
|
@ -6,15 +6,15 @@
|
||||
namespace EightBit {
|
||||
class Rom : public Memory {
|
||||
public:
|
||||
Rom(size_t size = 0)
|
||||
Rom(const size_t size = 0)
|
||||
: Memory(size) {
|
||||
}
|
||||
|
||||
uint8_t peek(uint16_t address) const {
|
||||
uint8_t peek(const uint16_t address) const {
|
||||
return read(address);
|
||||
}
|
||||
|
||||
uint8_t& reference(uint16_t address) {
|
||||
uint8_t& reference(const uint16_t address) {
|
||||
return BYTES()[address];
|
||||
}
|
||||
};
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <functional>
|
||||
|
||||
namespace EightBit {
|
||||
template<class T> class Signal {
|
||||
template<class T> class Signal final {
|
||||
private:
|
||||
typedef std::function<void(const T&)> delegate_t;
|
||||
typedef std::vector<delegate_t> delegates_t;
|
||||
@ -12,7 +12,7 @@ namespace EightBit {
|
||||
delegates_t m_delegates;
|
||||
|
||||
public:
|
||||
void connect(delegate_t functor) {
|
||||
void connect(const delegate_t functor) {
|
||||
m_delegates.push_back(functor);
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,7 @@ namespace EightBit {
|
||||
template<class ConfigurationT, class BoardT> class TestHarness {
|
||||
public:
|
||||
TestHarness(const ConfigurationT& configuration)
|
||||
: m_board(configuration),
|
||||
m_totalCycles(0),
|
||||
m_instructions(0),
|
||||
m_startHostCycles(0),
|
||||
m_finishHostCycles(0) {
|
||||
: m_board(configuration) {
|
||||
}
|
||||
|
||||
~TestHarness() {
|
||||
@ -81,12 +77,12 @@ namespace EightBit {
|
||||
|
||||
private:
|
||||
BoardT m_board;
|
||||
long long m_totalCycles;
|
||||
long long m_instructions;
|
||||
long long m_totalCycles = 0;
|
||||
long long m_instructions = 0;
|
||||
std::chrono::steady_clock::time_point m_startTime;
|
||||
std::chrono::steady_clock::time_point m_finishTime;
|
||||
uint64_t m_startHostCycles;
|
||||
uint64_t m_finishHostCycles;
|
||||
uint64_t m_startHostCycles = 0;
|
||||
uint64_t m_finishHostCycles = 0;
|
||||
|
||||
static std::chrono::steady_clock::time_point now() {
|
||||
return std::chrono::steady_clock::now();
|
||||
|
20
src/Bus.cpp
20
src/Bus.cpp
@ -11,7 +11,7 @@ uint8_t& EightBit::Bus::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_data = &m_temporary;
|
||||
return DATA();
|
||||
@ -22,17 +22,17 @@ uint8_t& EightBit::Bus::referenceDATA(uint8_t& value) {
|
||||
return DATA();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Bus::peek(uint16_t address) {
|
||||
uint8_t EightBit::Bus::peek(const uint16_t address) {
|
||||
bool 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;
|
||||
reference(address, rom) = value;
|
||||
}
|
||||
|
||||
uint16_t EightBit::Bus::peekWord(uint16_t address) {
|
||||
uint16_t EightBit::Bus::peekWord(const uint16_t address) {
|
||||
register16_t returned;
|
||||
returned.low = peek(address);
|
||||
returned.high = peek(address + 1);
|
||||
@ -46,28 +46,28 @@ uint8_t EightBit::Bus::read() {
|
||||
return returned;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Bus::read(uint16_t offset) {
|
||||
uint8_t EightBit::Bus::read(const uint16_t offset) {
|
||||
ADDRESS().word = offset;
|
||||
return read();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Bus::read(register16_t address) {
|
||||
uint8_t EightBit::Bus::read(const register16_t address) {
|
||||
ADDRESS() = address;
|
||||
return read();
|
||||
}
|
||||
|
||||
void EightBit::Bus::write(uint8_t value) {
|
||||
void EightBit::Bus::write(const uint8_t value) {
|
||||
WritingByte.fire(ADDRESS().word);
|
||||
reference() = value;
|
||||
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;
|
||||
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;
|
||||
write(value);
|
||||
}
|
||||
@ -75,5 +75,5 @@ void EightBit::Bus::write(register16_t address, uint8_t value) {
|
||||
uint8_t& EightBit::Bus::reference() {
|
||||
bool rom;
|
||||
auto& value = reference(ADDRESS().word, rom);
|
||||
return LIKELY(!rom) ? referenceDATA(value) : placeDATA(value);
|
||||
return rom ? placeDATA(value) : referenceDATA(value);
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
#include "stdafx.h"
|
||||
#include "InputOutput.h"
|
||||
|
||||
uint8_t EightBit::InputOutput::readInputPort(uint8_t port) {
|
||||
uint8_t EightBit::InputOutput::readInputPort(const uint8_t port) {
|
||||
OnReadingPort(port);
|
||||
const auto value = m_input[port];
|
||||
OnReadPort(port);
|
||||
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);
|
||||
m_output[port] = value;
|
||||
OnWrittenPort(port);
|
||||
}
|
||||
|
||||
void EightBit::InputOutput::OnReadingPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnReadingPort(const uint8_t port) {
|
||||
ReadingPort.fire(port);
|
||||
}
|
||||
|
||||
void EightBit::InputOutput::OnReadPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnReadPort(const uint8_t port) {
|
||||
ReadPort.fire(port);
|
||||
}
|
||||
|
||||
void EightBit::InputOutput::OnWritingPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnWritingPort(const uint8_t port) {
|
||||
WritingPort.fire(port);
|
||||
}
|
||||
|
||||
void EightBit::InputOutput::OnWrittenPort(uint8_t port) {
|
||||
void EightBit::InputOutput::OnWrittenPort(const uint8_t port) {
|
||||
WrittenPort.fire(port);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ void EightBit::IntelProcessor::reset() {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ EightBit::register16_t EightBit::IntelProcessor::getWord() {
|
||||
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(++BUS().ADDRESS().word, value.high);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ void EightBit::Processor::reset() {
|
||||
PC().word = 0;
|
||||
}
|
||||
|
||||
int EightBit::Processor::run(int limit) {
|
||||
int EightBit::Processor::run(const int limit) {
|
||||
int current = 0;
|
||||
while (LIKELY(powered()) && current < limit) {
|
||||
current += singleStep();
|
||||
|
Loading…
Reference in New Issue
Block a user