diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h
index ba976b3..989e418 100644
--- a/Intel8080/inc/Intel8080.h
+++ b/Intel8080/inc/Intel8080.h
@@ -79,8 +79,7 @@ namespace EightBit {
}
void adjustReservedFlags() {
- F() &= ~(Bit5 | Bit3);
- F() |= Bit1;
+ F() = (F() | Bit1) & ~(Bit5 | Bit3);
}
static void adjustAuxiliaryCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
@@ -150,9 +149,9 @@ namespace EightBit {
void dad(uint16_t value) {
auto& f = F();
- uint32_t sum = HL().word + value;
- setFlag(f, CF, sum > 0xffff);
- HL().word = (uint16_t)sum;
+ auto sum = HL().word + value;
+ setFlag(f, CF, sum & Bit16);
+ HL().word = sum;
}
void sub(uint8_t& operand, uint8_t value, int carry = 0) {
@@ -275,9 +274,9 @@ namespace EightBit {
m_memory.reference() = data;
}
- void lxi_b() { Processor::fetchWord(BC()); }
- void lxi_d() { Processor::fetchWord(DE()); }
- void lxi_h() { Processor::fetchWord(HL()); }
+ void lxi_b() { fetchWord(BC()); }
+ void lxi_d() { fetchWord(DE()); }
+ void lxi_h() { fetchWord(HL()); }
void stax_r(register16_t& destination) {
m_memory.ADDRESS() = destination;
@@ -351,7 +350,7 @@ namespace EightBit {
}
void lxi_sp() {
- Processor::fetchWord(SP());
+ fetchWord(SP());
}
void inx_sp() { ++SP().word; }
@@ -527,13 +526,11 @@ namespace EightBit {
}
void sbi() {
- auto value = fetchByte();
- sbb(value);
+ sbb(fetchByte());
}
void sui() {
- auto value = fetchByte();
- sub(value);
+ sub(fetchByte());
}
// logical
@@ -603,35 +600,31 @@ namespace EightBit {
void rlc() {
auto& a = A();
auto carry = a & Bit7;
- a <<= 1;
- carry ? a |= Bit0 : a &= ~Bit0;
+ a = (a << 1) | (carry >> 7);
setFlag(F(), CF, carry);
}
void rrc() {
auto& a = A();
auto carry = a & Bit0;
- a >>= 1;
- carry ? a |= Bit7 : a &= ~Bit7;
+ a = (a >> 1) | (carry << 7);
setFlag(F(), CF, carry);
}
void ral() {
auto& a = A();
auto& f = F();
- auto carry = a & Bit7;
- a <<= 1;
- a |= (f & CF);
- setFlag(f, CF, carry);
+ const auto carry = f & CF;
+ setFlag(f, CF, a & Bit7);
+ a = (a << 1) | carry;
}
void rar() {
auto& a = A();
auto& f = F();
- auto carry = a & 1;
- a >>= 1;
- a |= (f & CF) << 7;
- setFlag(f, CF, carry);
+ const auto carry = f & CF;
+ setFlag(f, CF, a & Bit0);
+ a = (a >> 1) | (carry << 7);
}
// specials
diff --git a/Intel8080/test/Board.h b/Intel8080/test/Board.h
index fa96247..85aea27 100644
--- a/Intel8080/test/Board.h
+++ b/Intel8080/test/Board.h
@@ -14,9 +14,8 @@ class Board {
public:
Board(const Configuration& configuration);
- EightBit::Memory& getMemory() { return m_memory; }
- const EightBit::Intel8080& getCPU() const { return m_cpu; }
- EightBit::Intel8080& getCPUMutable() { return m_cpu; }
+ EightBit::Memory& Memory() { return m_memory; }
+ EightBit::Intel8080& CPU() { return m_cpu; }
void initialise();
diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp
index 4e02ee5..248a533 100644
--- a/LR35902/src/LR35902.cpp
+++ b/LR35902/src/LR35902.cpp
@@ -524,7 +524,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
case 1: // 16-bit load immediate/add
switch (q) {
case 0: // LD rp,nn
- Processor::fetchWord(RP(p));
+ fetchWord(RP(p));
cycles += 3;
break;
case 1: // ADD HL,rp
diff --git a/LR35902/src/LR35902.vcxproj b/LR35902/src/LR35902.vcxproj
index ac9825d..d97bb84 100644
--- a/LR35902/src/LR35902.vcxproj
+++ b/LR35902/src/LR35902.vcxproj
@@ -22,7 +22,6 @@
{7730ECF5-8206-4ECB-BA6B-6B5CFE50CFB2}
Win32Proj
LR35902
- 8.1
diff --git a/M6502/inc/AddressEventArgs.h b/M6502/inc/AddressEventArgs.h
deleted file mode 100644
index b13d738..0000000
--- a/M6502/inc/AddressEventArgs.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#include
-
-class AddressEventArgs
-{
-private:
- uint16_t m_address;
- uint8_t m_cell;
-
-public:
- AddressEventArgs(uint16_t address, uint8_t cell)
- : m_address(address), m_cell(cell) {}
-
- uint16_t getAddress() const { return m_address; }
- uint8_t getCell() const { return m_cell; }
-};
diff --git a/M6502/inc/AddressingMode.h b/M6502/inc/AddressingMode.h
deleted file mode 100644
index 1f4db11..0000000
--- a/M6502/inc/AddressingMode.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-enum AddressingMode {
- Illegal,
- Implied,
- Accumulator,
- Immediate,
- Relative,
- XIndexed,
- IndexedY,
- ZeroPage,
- ZeroPageX,
- ZeroPageY,
- Absolute,
- AbsoluteX,
- AbsoluteY,
- AbsoluteXIndirect,
- Indirect,
- ZeroPageIndirect,
- ZeroPageRelative
-};
diff --git a/M6502/inc/AddressingModeDumper.h b/M6502/inc/AddressingModeDumper.h
deleted file mode 100644
index 57da6c7..0000000
--- a/M6502/inc/AddressingModeDumper.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include
-#include
-
-typedef std::function dumper_t;
-
-struct AddressingModeDumper {
- dumper_t byteDumper;
- dumper_t disassemblyDumper;
-};
diff --git a/M6502/inc/Disassembly.h b/M6502/inc/Disassembly.h
index 7239730..02b4722 100644
--- a/M6502/inc/Disassembly.h
+++ b/M6502/inc/Disassembly.h
@@ -3,62 +3,326 @@
#include
diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h
index 545c0f8..f0fcd52 100644
--- a/Z80/inc/Z80.h
+++ b/Z80/inc/Z80.h
@@ -9,6 +9,47 @@
namespace EightBit {
class Z80 : public IntelProcessor {
public:
+ struct refresh_t {
+
+ bool high : 1;
+ uint8_t variable : 7;
+
+ refresh_t(uint8_t value)
+ : high((value & Bit7) != 0),
+ variable(value & Mask7)
+ { }
+
+ operator uint8_t() const {
+ return (high << 7) | variable;
+ }
+
+ refresh_t& operator++() {
+ ++variable;
+ return *this;
+ }
+ };
+
+ struct opcode_decoded_t {
+
+ int x;
+ int y;
+ int z;
+ int p;
+ int q;
+
+ opcode_decoded_t() {
+ x = y = z = p = q = 0;
+ }
+
+ opcode_decoded_t(uint8_t opcode) {
+ x = (opcode & 0b11000000) >> 6; // 0 - 3
+ y = (opcode & 0b00111000) >> 3; // 0 - 7
+ z = (opcode & 0b00000111); // 0 - 7
+ p = (y & 0b110) >> 1; // 0 - 3
+ q = (y & 1); // 0 - 1
+ }
+ };
+
enum StatusBits {
SF = Bit7,
ZF = Bit6,
@@ -63,7 +104,7 @@ namespace EightBit {
uint8_t& IYH() { return IY().high; }
uint8_t& IYL() { return IY().low; }
- uint8_t& REFRESH() { return m_refresh; }
+ refresh_t& REFRESH() { return m_refresh; }
uint8_t& IV() { return iv; }
int& IM() { return m_interruptMode; }
bool& IFF1() { return m_iff1; }
@@ -96,7 +137,8 @@ namespace EightBit {
register16_t m_ix;
register16_t m_iy;
- uint8_t m_refresh;
+ refresh_t m_refresh;
+
uint8_t iv;
int m_interruptMode;
bool m_iff1;
@@ -112,21 +154,19 @@ namespace EightBit {
int8_t m_displacement;
bool m_displaced;
+ std::array m_decodedOpcodes;
+
int fetchExecute() {
M1() = true;
return execute(fetchByte());
}
- void incrementRefresh() {
- REFRESH() = (REFRESH() & Bit7) | (REFRESH() + 1) & Mask7;
- }
-
uint8_t& DISPLACED() {
m_memory.ADDRESS().word = MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
return m_memory.reference();
}
- uint8_t& R(int r) {
+ uint8_t& R(int r, uint8_t& a) {
switch (r) {
case 0:
return B();
@@ -141,19 +181,21 @@ namespace EightBit {
case 5:
return HL2().low;
case 6:
- if (m_displaced) {
- m_displacement = fetchByte();
- return DISPLACED();
+ if (!m_displaced) {
+ m_memory.ADDRESS() = HL();
+ return m_memory.reference();
}
- m_memory.ADDRESS() = HL();
- return m_memory.reference();
+ m_displacement = fetchByte();
+ return DISPLACED();
case 7:
- return A();
+ return a;
+ default:
+ __assume(0);
}
throw std::logic_error("Unhandled registry mechanism");
}
- uint8_t& R2(int r) {
+ uint8_t& R2(int r, uint8_t& a) {
switch (r) {
case 0:
return B();
@@ -171,12 +213,16 @@ namespace EightBit {
m_memory.ADDRESS() = HL();
return m_memory.reference();
case 7:
- return A();
+ return a;
+ default:
+ __assume(0);
}
throw std::logic_error("Unhandled registry mechanism");
}
register16_t& RP(int rp) {
+ __assume(rp < 4);
+ __assume(rp >= 0);
switch (rp) {
case 3:
return SP();
@@ -188,16 +234,17 @@ namespace EightBit {
}
register16_t& HL2() {
- if (m_displaced) {
- if (m_prefixDD)
- return IX();
- else if (m_prefixFD)
- return IY();
- }
- return HL();
+ if (!m_displaced)
+ return HL();
+ if (m_prefixDD)
+ return IX();
+ // Must be FD prefix
+ return IY();
}
register16_t& RP2(int rp) {
+ __assume(rp < 4);
+ __assume(rp >= 0);
switch (rp) {
case 3:
return AF();
@@ -208,21 +255,6 @@ namespace EightBit {
}
}
- void addViaMemptr(register16_t& hl, register16_t operand) {
- MEMPTR().word = hl.word + 1;
- add(hl, operand);
- }
-
- void sbcViaMemptr(register16_t& hl, register16_t operand) {
- MEMPTR().word = hl.word + 1;
- sbc(hl, operand);
- }
-
- void adcViaMemptr(register16_t& hl, register16_t operand) {
- MEMPTR().word = hl.word + 1;
- adc(hl, operand);
- }
-
static void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
}
@@ -249,98 +281,96 @@ namespace EightBit {
setFlag(f, VF, overflow);
}
- void executeCB(int x, int y, int z, int p, int q);
+ static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
+
+ void executeCB(int x, int y, int z);
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 postIncrement(uint8_t& f, uint8_t value);
- void postDecrement(uint8_t& f, uint8_t value);
+ static void postIncrement(uint8_t& f, uint8_t value);
+ static void postDecrement(uint8_t& f, uint8_t value);
void retn();
void reti();
- bool jrConditionalFlag(int flag);
- bool returnConditionalFlag(int flag);
- bool jumpConditionalFlag(int flag);
- bool callConditionalFlag(int flag);
+ bool jrConditionalFlag(uint8_t& f, int flag);
+ bool returnConditionalFlag(uint8_t& f, int flag);
+ bool jumpConditionalFlag(uint8_t& f, int flag);
+ bool callConditionalFlag(uint8_t& f, int flag);
- void sbc(register16_t& operand, register16_t value);
- void adc(register16_t& operand, register16_t value);
+ void sbc(uint8_t& f, register16_t& operand, register16_t value);
+ void adc(uint8_t& f, register16_t& operand, register16_t value);
+ void add(uint8_t& f, register16_t& operand, register16_t value);
- void add(register16_t& operand, register16_t value);
+ static void add(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
+ static void adc(uint8_t& f, uint8_t& operand, uint8_t value);
+ static void sub(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
+ static void sbc(uint8_t& f, uint8_t& operand, uint8_t value);
+ static void andr(uint8_t& f, uint8_t& operand, uint8_t value);
+ static void xorr(uint8_t& f, uint8_t& operand, uint8_t value);
+ static void orr(uint8_t& f, uint8_t& operand, uint8_t value);
+ static void compare(uint8_t& f, uint8_t check, uint8_t value);
- 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);
+ static uint8_t& rlc(uint8_t& f, uint8_t& operand);
+ static uint8_t& rrc(uint8_t& f, uint8_t& operand);
+ static uint8_t& rl(uint8_t& f, uint8_t& operand);
+ static uint8_t& rr(uint8_t& f, uint8_t& operand);
+ static uint8_t& sla(uint8_t& f, uint8_t& operand);
+ static uint8_t& sra(uint8_t& f, uint8_t& operand);
+ static uint8_t& sll(uint8_t& f, uint8_t& operand);
+ static uint8_t& srl(uint8_t& f, uint8_t& operand);
- uint8_t& rlc(uint8_t& operand);
- uint8_t& rrc(uint8_t& operand);
- uint8_t& rl(uint8_t& operand);
- uint8_t& rr(uint8_t& operand);
- uint8_t& sla(uint8_t& operand);
- uint8_t& sra(uint8_t& operand);
- uint8_t& sll(uint8_t& operand);
- uint8_t& srl(uint8_t& operand);
+ static uint8_t& bit(uint8_t& f, int n, uint8_t& operand);
+ static uint8_t& res(int n, uint8_t& operand);
+ static uint8_t& set(int nit, uint8_t& operand);
- uint8_t& bit(int n, uint8_t& operand);
- uint8_t& res(int n, uint8_t& operand);
- uint8_t& set(int nit, uint8_t& operand);
+ static void daa(uint8_t& a, uint8_t& f);
- void daa();
-
- void scf();
- void ccf();
- void cpl();
+ static void scf(uint8_t a, uint8_t& f);
+ static void ccf(uint8_t a, uint8_t& f);
+ static void cpl(uint8_t& a, uint8_t& f);
void xhtl(register16_t& operand);
- void xhtl();
- void blockCompare();
+ void blockCompare(uint8_t a, uint8_t& f);
- void cpi();
- bool cpir();
+ void cpi(uint8_t a, uint8_t& f);
+ bool cpir(uint8_t a, uint8_t& f);
- void cpd();
- bool cpdr();
+ void cpd(uint8_t a, uint8_t& f);
+ bool cpdr(uint8_t a, uint8_t& f);
- void blockLoad(register16_t source, register16_t destination);
+ void blockLoad(uint8_t a, uint8_t& f, register16_t source, register16_t destination);
- void ldi();
- bool ldir();
+ void ldi(uint8_t a, uint8_t& f);
+ bool ldir(uint8_t a, uint8_t& f);
- void ldd();
- bool lddr();
+ void ldd(uint8_t a, uint8_t& f);
+ bool lddr(uint8_t a, uint8_t& f);
- void ini();
- bool inir();
+ void ini(uint8_t& f);
+ bool inir(uint8_t& f);
- void ind();
- bool indr();
+ void ind(uint8_t& f);
+ bool indr(uint8_t& f);
- void blockOut();
+ void blockOut(uint8_t& f);
- void outi();
- bool otir();
+ void outi(uint8_t& f);
+ bool otir(uint8_t& f);
- void outd();
- bool otdr();
+ void outd(uint8_t& f);
+ bool otdr(uint8_t& f);
- void neg();
+ static void neg(uint8_t& a, uint8_t& f);
- void rrd();
- void rld();
+ void rrd(uint8_t& a, uint8_t& f);
+ void rld(uint8_t& a, uint8_t& f);
- void writePort() {
- m_ports.write(m_memory.ADDRESS().low, m_memory.DATA());
- }
+ void writePort(uint8_t port, uint8_t a);
+ void writePort();
- void readPort() {
- m_memory.placeDATA(m_ports.read(m_memory.ADDRESS().low));
- }
+ void readPort(uint8_t port, uint8_t& a);
+ void readPort();
};
}
\ No newline at end of file
diff --git a/Z80/src/Disassembler.cpp b/Z80/src/Disassembler.cpp
index 6524d02..d738a75 100644
--- a/Z80/src/Disassembler.cpp
+++ b/Z80/src/Disassembler.cpp
@@ -31,7 +31,7 @@ std::string EightBit::Disassembler::state(Z80& cpu) {
auto l = cpu.L();
auto i = cpu.IV();
- auto r = cpu.REFRESH();
+ uint8_t r = cpu.REFRESH();
auto im = cpu.IM();
diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp
index 6502a15..5d037cd 100644
--- a/Z80/src/Z80.cpp
+++ b/Z80/src/Z80.cpp
@@ -34,6 +34,10 @@ void EightBit::Z80::initialise() {
IntelProcessor::initialise();
+ for (int i = 0; i < 0x100; ++i) {
+ m_decodedOpcodes[i] = i;
+ }
+
IM() = 0;
AF().word = 0xffff;
@@ -126,46 +130,50 @@ void EightBit::Z80::postDecrement(uint8_t& f, uint8_t value) {
#pragma region PC manipulation: call/ret/jp/jr
-bool EightBit::Z80::jrConditionalFlag(int flag) {
+bool EightBit::Z80::jrConditionalFlag(uint8_t& f, int flag) {
switch (flag) {
case 0: // NZ
- return jrConditional(!(F() & ZF));
+ return jrConditional(!(f & ZF));
case 1: // Z
- return jrConditional(F() & ZF);
+ return jrConditional(f & ZF);
case 2: // NC
- return jrConditional(!(F() & CF));
+ return jrConditional(!(f & CF));
case 3: // C
- return jrConditional(F() & CF);
+ return jrConditional(f & CF);
case 4: // PO
- return jrConditional(!(F() & PF));
+ return jrConditional(!(f & PF));
case 5: // PE
- return jrConditional(F() & PF);
+ return jrConditional(f & PF);
case 6: // P
- return jrConditional(!(F() & SF));
+ return jrConditional(!(f & SF));
case 7: // M
- return jrConditional(F() & SF);
+ return jrConditional(f & SF);
+ default:
+ __assume(0);
}
throw std::logic_error("Unhandled JR conditional");
}
-bool EightBit::Z80::jumpConditionalFlag(int flag) {
+bool EightBit::Z80::jumpConditionalFlag(uint8_t& f, int flag) {
switch (flag) {
case 0: // NZ
- return jumpConditional(!(F() & ZF));
+ return jumpConditional(!(f & ZF));
case 1: // Z
- return jumpConditional(F() & ZF);
+ return jumpConditional(f & ZF);
case 2: // NC
- return jumpConditional(!(F() & CF));
+ return jumpConditional(!(f & CF));
case 3: // C
- return jumpConditional(F() & CF);
+ return jumpConditional(f & CF);
case 4: // PO
- return jumpConditional(!(F() & PF));
+ return jumpConditional(!(f & PF));
case 5: // PE
- return jumpConditional(F() & PF);
+ return jumpConditional(f & PF);
case 6: // P
- return jumpConditional(!(F() & SF));
+ return jumpConditional(!(f & SF));
case 7: // M
- return jumpConditional(F() & SF);
+ return jumpConditional(f & SF);
+ default:
+ __assume(0);
}
throw std::logic_error("Unhandled JP conditional");
}
@@ -179,46 +187,50 @@ void EightBit::Z80::reti() {
retn();
}
-bool EightBit::Z80::returnConditionalFlag(int flag) {
+bool EightBit::Z80::returnConditionalFlag(uint8_t& f, int flag) {
switch (flag) {
case 0: // NZ
- return returnConditional(!(F() & ZF));
+ return returnConditional(!(f & ZF));
case 1: // Z
- return returnConditional(F() & ZF);
+ return returnConditional(f & ZF);
case 2: // NC
- return returnConditional(!(F() & CF));
+ return returnConditional(!(f & CF));
case 3: // C
- return returnConditional(F() & CF);
+ return returnConditional(f & CF);
case 4: // PO
- return returnConditional(!(F() & PF));
+ return returnConditional(!(f & PF));
case 5: // PE
- return returnConditional(F() & PF);
+ return returnConditional(f & PF);
case 6: // P
- return returnConditional(!(F() & SF));
+ return returnConditional(!(f & SF));
case 7: // M
- return returnConditional(F() & SF);
+ return returnConditional(f & SF);
+ default:
+ __assume(0);
}
throw std::logic_error("Unhandled RET conditional");
}
-bool EightBit::Z80::callConditionalFlag(int flag) {
+bool EightBit::Z80::callConditionalFlag(uint8_t& f, int flag) {
switch (flag) {
case 0: // NZ
- return callConditional(!(F() & ZF));
+ return callConditional(!(f & ZF));
case 1: // Z
- return callConditional(F() & ZF);
+ return callConditional(f & ZF);
case 2: // NC
- return callConditional(!(F() & CF));
+ return callConditional(!(f & CF));
case 3: // C
- return callConditional(F() & CF);
+ return callConditional(f & CF);
case 4: // PO
- return callConditional(!(F() & PF));
+ return callConditional(!(f & PF));
case 5: // PE
- return callConditional(F() & PF);
+ return callConditional(f & PF);
case 6: // P
- return callConditional(!(F() & SF));
+ return callConditional(!(f & SF));
case 7: // M
- return callConditional(F() & SF);
+ return callConditional(f & SF);
+ default:
+ __assume(0);
}
throw std::logic_error("Unhandled CALL conditional");
}
@@ -227,75 +239,73 @@ bool EightBit::Z80::callConditionalFlag(int flag) {
#pragma region 16-bit arithmetic
-void EightBit::Z80::sbc(register16_t& operand, register16_t value) {
+void EightBit::Z80::sbc(uint8_t& f, register16_t& operand, register16_t value) {
- auto& f = F();
+ MEMPTR() = operand;
- auto before = operand;
+ const auto beforeNegative = MEMPTR().high & SF;
+ const auto valueNegative = value.high & SF;
- auto beforeNegative = before.high & SF;
- auto valueNegative = value.high & SF;
+ const auto result = MEMPTR().word - value.word - (f & CF);
+ operand.word = result;
- auto result = before.word - value.word - (f & CF);
+ const auto afterNegative = operand.high & SF;
+
+ setFlag(f, SF, afterNegative);
+ clearFlag(f, ZF, operand.word);
+ adjustHalfCarrySub(f, MEMPTR().high, value.high, operand.high);
+ adjustOverflowSub(f, beforeNegative, valueNegative, afterNegative);
+ setFlag(f, NF);
+ setFlag(f, CF, result & Bit16);
+ adjustXY(f, operand.high);
+
+ MEMPTR().word++;
+}
+
+void EightBit::Z80::adc(uint8_t& f, register16_t& operand, register16_t value) {
+
+ MEMPTR() = operand;
+
+ const auto beforeNegative = MEMPTR().high & SF;
+ const auto valueNegative = value.high & SF;
+
+ const auto result = MEMPTR().word + value.word + (f & CF);
operand.word = result;
auto afterNegative = operand.high & SF;
setFlag(f, SF, afterNegative);
clearFlag(f, ZF, operand.word);
- adjustHalfCarrySub(f, before.high, value.high, operand.high);
- adjustOverflowSub(f, beforeNegative, valueNegative, afterNegative);
- setFlag(f, NF);
- setFlag(f, CF, result & Bit16);
- adjustXY(f, operand.high);
-}
-
-void EightBit::Z80::adc(register16_t& operand, register16_t value) {
-
- auto& f = F();
-
- auto before = operand;
-
- auto beforeNegative = before.high & SF;
- auto valueNegative = value.high & SF;
-
- auto result = before.word + value.word + (f & CF);
- operand.word = result;
-
- auto afterNegative = operand.high & SF;
-
- setFlag(f, SF, afterNegative);
- clearFlag(f, ZF, result);
- adjustHalfCarryAdd(f, before.high, value.high, operand.high);
+ adjustHalfCarryAdd(f, MEMPTR().high, value.high, operand.high);
adjustOverflowAdd(f, beforeNegative, valueNegative, afterNegative);
clearFlag(f, NF);
setFlag(f, CF, result & Bit16);
adjustXY(f, operand.high);
+
+ MEMPTR().word++;
}
-void EightBit::Z80::add(register16_t& operand, register16_t value) {
+void EightBit::Z80::add(uint8_t& f, register16_t& operand, register16_t value) {
- auto& f = F();
+ MEMPTR() = operand;
- auto before = operand;
-
- auto result = before.word + value.word;
+ const auto result = MEMPTR().word + value.word;
operand.word = result;
clearFlag(f, NF);
setFlag(f, CF, result & Bit16);
- adjustHalfCarryAdd(f, before.high, value.high, operand.high);
+ adjustHalfCarryAdd(f, MEMPTR().high, value.high, operand.high);
adjustXY(f, operand.high);
+
+ MEMPTR().word++;
}
#pragma endregion 16-bit arithmetic
#pragma region ALU
-void EightBit::Z80::add(uint8_t& operand, uint8_t value, int carry) {
-
- auto& f = F();
+void EightBit::Z80::add(uint8_t& f, uint8_t& operand, uint8_t value, int carry) {
register16_t result;
result.word = operand + value + carry;
@@ -310,13 +320,11 @@ void EightBit::Z80::add(uint8_t& operand, uint8_t value, int carry) {
adjustSZXY(f, operand);
}
-void EightBit::Z80::adc(uint8_t& operand, uint8_t value) {
- add(operand, value, F() & CF);
+void EightBit::Z80::adc(uint8_t& f, uint8_t& operand, uint8_t value) {
+ add(f, operand, value, f & CF);
}
-void EightBit::Z80::sub(uint8_t& operand, uint8_t value, int carry) {
-
- auto& f = F();
+void EightBit::Z80::subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry) {
register16_t result;
result.word = operand - value - carry;
@@ -328,133 +336,107 @@ void EightBit::Z80::sub(uint8_t& operand, uint8_t value, int carry) {
setFlag(f, NF);
setFlag(f, CF, result.word & Bit8);
- adjustSZXY(f, operand);
+ adjustSZ(f, operand);
}
-void EightBit::Z80::sbc(uint8_t& operand, uint8_t value) {
- sub(operand, value, F() & CF);
+void EightBit::Z80::sub(uint8_t& f, uint8_t& operand, uint8_t value, int carry) {
+ subtract(f, operand, value, carry);
+ adjustXY(f, operand);
}
-void EightBit::Z80::andr(uint8_t& operand, uint8_t value) {
- auto& f = F();
- operand &= value;
+void EightBit::Z80::sbc(uint8_t& f, uint8_t& operand, uint8_t value) {
+ sub(f, operand, value, f & CF);
+}
+
+void EightBit::Z80::andr(uint8_t& f, uint8_t& operand, uint8_t value) {
setFlag(f, HC);
clearFlag(f, CF | NF);
- adjustSZPXY(f, operand);
+ adjustSZPXY(f, operand &= value);
}
-void EightBit::Z80::xorr(uint8_t& operand, uint8_t value) {
- auto& f = F();
- operand ^= value;
+void EightBit::Z80::xorr(uint8_t& f, uint8_t& operand, uint8_t value) {
clearFlag(f, HC | CF | NF);
- adjustSZPXY(f, operand);
+ adjustSZPXY(f, operand ^= value);
}
-void EightBit::Z80::orr(uint8_t& operand, uint8_t value) {
- auto& f = F();
- operand |= value;
+void EightBit::Z80::orr(uint8_t& f, uint8_t& operand, uint8_t value) {
clearFlag(f, HC | CF | NF);
- adjustSZPXY(f, operand);
+ adjustSZPXY(f, operand |= value);
}
-void EightBit::Z80::compare(uint8_t value) {
- auto check = A();
- sub(check, value);
- adjustXY(F(), value);
+void EightBit::Z80::compare(uint8_t& f, uint8_t check, uint8_t value) {
+ subtract(f, check, value);
+ adjustXY(f, value);
}
#pragma endregion ALU
#pragma region Shift and rotate
-uint8_t& EightBit::Z80::rlc(uint8_t& operand) {
- auto& f = F();
- auto carry = operand & Bit7;
- operand <<= 1;
- carry ? operand |= Bit0 : operand &= ~Bit0;
- setFlag(f, CF, carry);
+uint8_t& EightBit::Z80::rlc(uint8_t& f, uint8_t& operand) {
clearFlag(f, NF | HC);
+ setFlag(f, CF, operand & Bit7);
+ operand = _rotl8(operand, 1);
adjustXY(f, operand);
return operand;
}
-uint8_t& EightBit::Z80::rrc(uint8_t& operand) {
- auto& f = F();
- auto carry = operand & Bit0;
- operand >>= 1;
- carry ? operand |= Bit7 : operand &= ~Bit7;
- setFlag(f, CF, carry);
+uint8_t& EightBit::Z80::rrc(uint8_t& f, uint8_t& operand) {
clearFlag(f, NF | HC);
+ setFlag(f, CF, operand & Bit0);
+ operand = _rotr8(operand, 1);
adjustXY(f, operand);
return operand;
}
-uint8_t& EightBit::Z80::rl(uint8_t& operand) {
- auto& f = F();
- auto oldCarry = f & CF;
- auto newCarry = operand & Bit7;
- operand <<= 1;
- oldCarry ? operand |= Bit0 : operand &= ~Bit0;
- setFlag(f, CF, newCarry);
+uint8_t& EightBit::Z80::rl(uint8_t& f, uint8_t& operand) {
clearFlag(f, NF | HC);
+ const auto carry = f & CF;
+ setFlag(f, CF, operand & Bit7);
+ operand = (operand << 1) | carry;
adjustXY(f, operand);
return operand;
}
-uint8_t& EightBit::Z80::rr(uint8_t& operand) {
- auto& f = F();
- auto oldCarry = f & CF;
- auto newCarry = operand & Bit0;
- operand >>= 1;
- operand |= oldCarry << 7;
- setFlag(f, CF, newCarry);
+uint8_t& EightBit::Z80::rr(uint8_t& f, uint8_t& operand) {
clearFlag(f, NF | HC);
+ const auto carry = f & CF;
+ setFlag(f, CF, operand & Bit0);
+ operand = (operand >> 1) | (carry << 7);
adjustXY(f, operand);
return operand;
}
//
-uint8_t& EightBit::Z80::sla(uint8_t& operand) {
- auto& f = F();
- auto newCarry = operand & Bit7;
+uint8_t& EightBit::Z80::sla(uint8_t& f, uint8_t& operand) {
+ clearFlag(f, NF | HC);
+ setFlag(f, CF, operand & Bit7);
operand <<= 1;
- setFlag(f, CF, newCarry);
- clearFlag(f, NF | HC);
adjustXY(f, operand);
return operand;
}
-uint8_t& EightBit::Z80::sra(uint8_t& operand) {
- auto& f = F();
- auto new7 = operand & Bit7;
- auto newCarry = operand & Bit0;
- operand >>= 1;
- operand |= new7;
- setFlag(f, CF, newCarry);
+uint8_t& EightBit::Z80::sra(uint8_t& f, uint8_t& operand) {
clearFlag(f, NF | HC);
+ setFlag(f, CF, operand & Bit0);
+ operand = (operand >> 1) | operand & Bit7;
adjustXY(f, operand);
return operand;
}
-uint8_t& EightBit::Z80::sll(uint8_t& operand) {
- auto& f = F();
- auto newCarry = operand & Bit7;
- operand <<= 1;
- operand |= 1;
- setFlag(f, CF, newCarry);
+uint8_t& EightBit::Z80::sll(uint8_t& f, uint8_t& operand) {
clearFlag(f, NF | HC);
+ setFlag(f, CF, operand & Bit7);
+ operand = (operand << 1) | Bit0;
adjustXY(f, operand);
return operand;
}
-uint8_t& EightBit::Z80::srl(uint8_t& operand) {
- auto& f = F();
- auto newCarry = operand & Bit0;
- operand >>= 1;
- operand &= ~Bit7; // clear bit 7
- setFlag(f, CF, newCarry);
+uint8_t& EightBit::Z80::srl(uint8_t& f, uint8_t& operand) {
clearFlag(f, NF | HC);
+ setFlag(f, CF, operand & Bit0);
+ operand = (operand >> 1) & ~Bit7;
adjustXY(f, operand);
setFlag(f, ZF, operand);
return operand;
@@ -464,93 +446,85 @@ uint8_t& EightBit::Z80::srl(uint8_t& operand) {
#pragma region BIT/SET/RES
-uint8_t& EightBit::Z80::bit(int n, uint8_t& operand) {
- auto& f = F();
- auto carry = f & CF;
- uint8_t discarded = operand;
- andr(discarded, 1 << n);
+uint8_t& EightBit::Z80::bit(uint8_t& f, int n, uint8_t& operand) {
+ setFlag(f, HC);
+ clearFlag(f, NF);
+ const auto discarded = operand & (1 << n);
+ adjustSZXY(f, discarded);
clearFlag(f, PF, discarded);
- setFlag(f, CF, carry);
return operand;
}
uint8_t& EightBit::Z80::res(int n, uint8_t& operand) {
- auto bit = 1 << n;
- operand &= ~bit;
- return operand;
+ return operand &= ~(1 << n);
}
uint8_t& EightBit::Z80::set(int n, uint8_t& operand) {
- auto bit = 1 << n;
- operand |= bit;
- return operand;
+ return operand |= (1 << n);
}
#pragma endregion BIT/SET/RES
#pragma region Miscellaneous instructions
-void EightBit::Z80::neg() {
- auto& a = A();
- auto& f = F();
- auto original = a;
- a = 0;
- sub(a, original);
- setFlag(f, PF, original == Bit7);
- setFlag(f, CF, original);
+void EightBit::Z80::neg(uint8_t& a, uint8_t& f) {
+
+ setFlag(f, PF, a == Bit7);
+ setFlag(f, CF, a);
+ setFlag(f, NF);
+
+ const auto original = a;
+
+ a = (~a + 1); // two's complement
+
+ adjustHalfCarrySub(f, 0U, original, a);
+ adjustOverflowSub(f, 0U, original, a);
+
+ adjustSZXY(f, a);
}
-void EightBit::Z80::daa() {
+void EightBit::Z80::daa(uint8_t& a, uint8_t& f) {
- auto& acc = A();
- auto& f = F();
+ auto updated = a;
- auto a = acc;
-
- auto lowAdjust = (f & HC) | (lowNibble(acc) > 9);
- auto highAdjust = (f & CF) | (acc > 0x99);
+ auto lowAdjust = (f & HC) | (lowNibble(a) > 9);
+ auto highAdjust = (f & CF) | (a > 0x99);
if (f & NF) {
if (lowAdjust)
- a -= 6;
+ updated -= 6;
if (highAdjust)
- a -= 0x60;
+ updated -= 0x60;
} else {
if (lowAdjust)
- a += 6;
+ updated += 6;
if (highAdjust)
- a += 0x60;
+ updated += 0x60;
}
- f = (f & (CF | NF)) | (acc > 0x99) | ((acc ^ a) & HC);
+ f = (f & (CF | NF)) | (a > 0x99) | ((a ^ updated) & HC);
+ a = updated;
adjustSZPXY(f, a);
-
- acc = a;
}
-void EightBit::Z80::cpl() {
- auto& a = A();
- auto& f = F();
- a = ~a;
- adjustXY(f, A());
+void EightBit::Z80::cpl(uint8_t& a, uint8_t& f) {
setFlag(f, HC | NF);
+ adjustXY(f, a = ~a);
}
-void EightBit::Z80::scf() {
- auto& f = F();
+void EightBit::Z80::scf(uint8_t a, uint8_t& f) {
setFlag(f, CF);
- adjustXY(f, A());
clearFlag(f, HC | NF);
+ adjustXY(f, a);
}
-void EightBit::Z80::ccf() {
- auto& f = F();
- auto carry = f & CF;
+void EightBit::Z80::ccf(uint8_t a, uint8_t& f) {
+ clearFlag(f, NF);
+ const auto carry = f & CF;
setFlag(f, HC, carry);
clearFlag(f, CF, carry);
- clearFlag(f, NF);
- adjustXY(f, A());
+ adjustXY(f, a);
}
void EightBit::Z80::xhtl(register16_t& operand) {
@@ -564,24 +538,17 @@ void EightBit::Z80::xhtl(register16_t& operand) {
operand.high = MEMPTR().high;
}
-void EightBit::Z80::xhtl() {
- xhtl(HL2());
-}
-
#pragma endregion Miscellaneous instructions
#pragma region Block instructions
#pragma region Block compare instructions
-void EightBit::Z80::blockCompare() {
-
- const auto& a = A();
- auto& f = F();
+void EightBit::Z80::blockCompare(uint8_t a, uint8_t& f) {
m_memory.ADDRESS() = HL();
- auto value = m_memory.reference();
+ const auto value = m_memory.reference();
uint8_t result = a - value;
setFlag(f, PF, --BC().word);
@@ -590,38 +557,37 @@ void EightBit::Z80::blockCompare() {
adjustHalfCarrySub(f, a, value, result);
setFlag(f, NF);
- if (f & HC)
- result -= 1;
+ result -= ((f & HC) >> 4);
setFlag(f, YF, result & Bit1);
setFlag(f, XF, result & Bit3);
}
-void EightBit::Z80::cpi() {
- blockCompare();
+void EightBit::Z80::cpi(uint8_t a, uint8_t& f) {
+ blockCompare(a, f);
HL().word++;
MEMPTR().word++;
}
-void EightBit::Z80::cpd() {
- blockCompare();
+void EightBit::Z80::cpd(uint8_t a, uint8_t& f) {
+ blockCompare(a, f);
HL().word--;
MEMPTR().word--;
}
-bool EightBit::Z80::cpir() {
- cpi();
+bool EightBit::Z80::cpir(uint8_t a, uint8_t& f) {
+ cpi(a, f);
MEMPTR() = PC();
- auto again = (F() & PF) && !(F() & ZF); // See CPI
+ auto again = (f & PF) && !(f & ZF); // See CPI
if (again)
MEMPTR().word--;
return again;
}
-bool EightBit::Z80::cpdr() {
- cpd();
+bool EightBit::Z80::cpdr(uint8_t a, uint8_t& f) {
+ cpd(a, f);
MEMPTR().word = PC().word - 1;
- auto again = (F() & PF) && !(F() & ZF); // See CPD
+ auto again = (f & PF) && !(f & ZF); // See CPD
if (!again)
MEMPTR().word--;
return again;
@@ -631,42 +597,41 @@ bool EightBit::Z80::cpdr() {
#pragma region Block load instructions
-void EightBit::Z80::blockLoad(register16_t source, register16_t destination) {
- auto& f = F();
+void EightBit::Z80::blockLoad(uint8_t a, uint8_t& f, register16_t source, register16_t destination) {
m_memory.ADDRESS() = source;
auto value = m_memory.reference();
m_memory.ADDRESS() = destination;
m_memory.reference() = value;
- auto xy = A() + value;
+ auto xy = a + value;
setFlag(f, XF, xy & 8);
setFlag(f, YF, xy & 2);
clearFlag(f, NF | HC);
setFlag(f, PF, --BC().word);
}
-void EightBit::Z80::ldd() {
- blockLoad(HL(), DE());
+void EightBit::Z80::ldd(uint8_t a, uint8_t& f) {
+ blockLoad(a, f, HL(), DE());
HL().word--;
DE().word--;
}
-void EightBit::Z80::ldi() {
- blockLoad(HL(), DE());
+void EightBit::Z80::ldi(uint8_t a, uint8_t& f) {
+ blockLoad(a, f, HL(), DE());
HL().word++;
DE().word++;
}
-bool EightBit::Z80::ldir() {
- ldi();
- auto again = (F() & PF) != 0;
+bool EightBit::Z80::ldir(uint8_t a, uint8_t& f) {
+ ldi(a, f);
+ auto again = (f & PF) != 0;
if (again) // See LDI
MEMPTR().word = PC().word - 1;
return again;
}
-bool EightBit::Z80::lddr() {
- ldd();
- auto again = (F() & PF) != 0;
+bool EightBit::Z80::lddr(uint8_t a, uint8_t& f) {
+ ldd(a, f);
+ auto again = (f & PF) != 0;
if (again) // See LDR
MEMPTR().word = PC().word - 1;
return again;
@@ -676,8 +641,7 @@ bool EightBit::Z80::lddr() {
#pragma region Block input instructions
-void EightBit::Z80::ini() {
- auto& f = F();
+void EightBit::Z80::ini(uint8_t& f) {
MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word++;
readPort();
@@ -688,8 +652,7 @@ void EightBit::Z80::ini() {
setFlag(f, NF);
}
-void EightBit::Z80::ind() {
- auto& f = F();
+void EightBit::Z80::ind(uint8_t& f) {
MEMPTR() = m_memory.ADDRESS() = BC();
MEMPTR().word--;
readPort();
@@ -700,22 +663,21 @@ void EightBit::Z80::ind() {
setFlag(f, NF);
}
-bool EightBit::Z80::inir() {
- ini();
- return !(F() & ZF); // See INI
+bool EightBit::Z80::inir(uint8_t& f) {
+ ini(f);
+ return !(f & ZF); // See INI
}
-bool EightBit::Z80::indr() {
- ind();
- return !(F() & ZF); // See IND
+bool EightBit::Z80::indr(uint8_t& f) {
+ ind(f);
+ return !(f & ZF); // See IND
}
#pragma endregion Block input instructions
#pragma region Block output instructions
-void EightBit::Z80::blockOut() {
- auto& f = F();
+void EightBit::Z80::blockOut(uint8_t& f) {
auto value = m_memory.reference();
m_memory.ADDRESS().word = BC().word;
writePort();
@@ -725,26 +687,26 @@ void EightBit::Z80::blockOut() {
adjustParity(f, ((value + L()) & 7) ^ B());
}
-void EightBit::Z80::outi() {
+void EightBit::Z80::outi(uint8_t& f) {
m_memory.ADDRESS().word = HL().word++;
- blockOut();
+ blockOut(f);
MEMPTR().word = BC().word + 1;
}
-void EightBit::Z80::outd() {
+void EightBit::Z80::outd(uint8_t& f) {
m_memory.ADDRESS().word = HL().word--;
- blockOut();
+ blockOut(f);
MEMPTR().word = BC().word - 1;
}
-bool EightBit::Z80::otir() {
- outi();
- return !(F() & ZF); // See OUTI
+bool EightBit::Z80::otir(uint8_t& f) {
+ outi(f);
+ return !(f & ZF); // See OUTI
}
-bool EightBit::Z80::otdr() {
- outd();
- return !(F() & ZF); // See OUTD
+bool EightBit::Z80::otdr(uint8_t& f) {
+ outd(f);
+ return !(f & ZF); // See OUTD
}
#pragma endregion Block output instructions
@@ -753,9 +715,7 @@ bool EightBit::Z80::otdr() {
#pragma region Nibble rotation
-void EightBit::Z80::rrd() {
- auto& a = A();
- auto& f = F();
+void EightBit::Z80::rrd(uint8_t& a, uint8_t& f) {
MEMPTR() = HL();
auto memory = memptrReference();
m_memory.reference() = promoteNibble(a) | highNibble(memory);
@@ -764,9 +724,7 @@ void EightBit::Z80::rrd() {
clearFlag(f, NF | HC);
}
-void EightBit::Z80::rld() {
- auto& a = A();
- auto& f = F();
+void EightBit::Z80::rld(uint8_t& a, uint8_t& f) {
MEMPTR() = HL();
auto memory = memptrReference();
m_memory.reference() = promoteNibble(memory) | lowNibble(a);
@@ -777,6 +735,36 @@ void EightBit::Z80::rld() {
#pragma endregion Nibble rotation
+#pragma region I/O instructions
+
+void EightBit::Z80::writePort(uint8_t port, uint8_t data) {
+ m_memory.ADDRESS().low = port;
+ m_memory.ADDRESS().high = data;
+ MEMPTR() = m_memory.ADDRESS();
+ m_memory.placeDATA(data);
+ writePort();
+ MEMPTR().low++;
+}
+
+void EightBit::Z80::writePort() {
+ m_ports.write(m_memory.ADDRESS().low, m_memory.DATA());
+}
+
+void EightBit::Z80::readPort(uint8_t port, uint8_t& a) {
+ m_memory.ADDRESS().low = port;
+ m_memory.ADDRESS().high = a;
+ MEMPTR() = m_memory.ADDRESS();
+ readPort();
+ a = m_memory.DATA();
+ MEMPTR().low++;
+}
+
+void EightBit::Z80::readPort() {
+ m_memory.placeDATA(m_ports.read(m_memory.ADDRESS().low));
+}
+
+#pragma endregion I/O instructions
+
int EightBit::Z80::step() {
ExecutingInstruction.fire(*this);
m_displaced = m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
@@ -789,24 +777,29 @@ int EightBit::Z80::execute(uint8_t opcode) {
if (!M1())
throw std::logic_error("M1 cannot be high");
- auto x = (opcode & 0b11000000) >> 6;
- auto y = (opcode & 0b111000) >> 3;
- auto z = (opcode & 0b111);
-
- auto p = (y & 0b110) >> 1;
- auto q = (y & 1);
-
if (!(m_prefixCB && m_displaced)) {
- incrementRefresh();
+ ++REFRESH();
M1() = false;
}
- if (m_prefixCB)
- executeCB(x, y, z, p, q);
- else if (m_prefixED)
- executeED(x, y, z, p, q);
- else
+ const auto& decoded = m_decodedOpcodes[opcode];
+
+ auto x = decoded.x;
+ auto y = decoded.y;
+ auto z = decoded.z;
+
+ auto p = decoded.p;
+ auto q = decoded.q;
+
+ auto prefixed = m_prefixCB || m_prefixED;
+ if (!prefixed) {
executeOther(x, y, z, p, q);
+ } else {
+ if (m_prefixCB)
+ executeCB(x, y, z);
+ else if (m_prefixED)
+ executeED(x, y, z, p, q);
+ }
if (cycles == 0)
throw std::logic_error("Unhandled opcode");
@@ -814,86 +807,90 @@ int EightBit::Z80::execute(uint8_t opcode) {
return cycles;
}
-void EightBit::Z80::executeCB(int x, int y, int z, int p, int q) {
+void EightBit::Z80::executeCB(int x, int y, int z) {
+ auto& a = A();
auto& f = F();
switch (x) {
case 0: // rot[y] r[z]
switch (y) {
case 0:
- adjustSZP(f, m_displaced ? R2(z) = rlc(DISPLACED()) : rlc(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = rlc(f, DISPLACED()) : rlc(f, R(z, a)));
break;
case 1:
- adjustSZP(f, m_displaced ? R2(z) = rrc(DISPLACED()) : rrc(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = rrc(f, DISPLACED()) : rrc(f, R(z, a)));
break;
case 2:
- adjustSZP(f, m_displaced ? R2(z) = rl(DISPLACED()) : rl(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = rl(f, DISPLACED()) : rl(f, R(z, a)));
break;
case 3:
- adjustSZP(f, m_displaced ? R2(z) = rr(DISPLACED()) : rr(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = rr(f, DISPLACED()) : rr(f, R(z, a)));
break;
case 4:
- adjustSZP(f, m_displaced ? R2(z) = sla(DISPLACED()) : sla(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = sla(f, DISPLACED()) : sla(f, R(z, a)));
break;
case 5:
- adjustSZP(f, m_displaced ? R2(z) = sra(DISPLACED()) : sra(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = sra(f, DISPLACED()) : sra(f, R(z, a)));
break;
case 6:
- adjustSZP(f, m_displaced ? R2(z) = sll(DISPLACED()) : sll(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = sll(f, DISPLACED()) : sll(f, R(z, a)));
break;
case 7:
- adjustSZP(f, m_displaced ? R2(z) = srl(DISPLACED()) : srl(R(z)));
+ adjustSZP(f, m_displaced ? R2(z, a) = srl(f, DISPLACED()) : srl(f, R(z, a)));
break;
}
- if (m_displaced) {
- cycles += 23;
- } else {
- cycles += 8;
+ cycles += 8;
+ if (!m_displaced) {
if (z == 6)
cycles += 7;
+ } else {
+ cycles += 15;
}
break;
case 1: // BIT y, r[z]
- if (m_displaced) {
- bit(y, DISPLACED());
- adjustXY(f, MEMPTR().high);
- cycles += 20;
- } else {
- auto operand = bit(y, R(z));
- cycles += 8;
+ cycles += 8;
+ if (!m_displaced) {
+ auto operand = bit(f, y, R(z, a));
if (z == 6) {
adjustXY(f, MEMPTR().high);
cycles += 4;
} else {
adjustXY(f, operand);
}
+ } else {
+ bit(f, y, DISPLACED());
+ adjustXY(f, MEMPTR().high);
+ cycles += 12;
}
break;
case 2: // RES y, r[z]
- if (m_displaced) {
- R2(z) = res(y, DISPLACED());
- cycles += 23;
- } else {
- res(y, R(z));
- cycles += 8;
+ cycles += 8;
+ if (!m_displaced) {
+ res(y, R(z, a));
if (z == 6)
cycles += 7;
+ } else {
+ R2(z, a) = res(y, DISPLACED());
+ cycles += 15;
}
break;
case 3: // SET y, r[z]
- if (m_displaced) {
- R2(z) = set(y, DISPLACED());
- cycles += 23;
- } else {
- set(y, R(z));
- cycles += 8;
+ cycles += 8;
+ if (!m_displaced) {
+ set(y, R(z, a));
if (z == 6)
cycles += 7;
+ } else {
+ R2(z, a) = set(y, DISPLACED());
+ cycles += 15;
}
break;
+ default:
+ __assume(0);
}
}
void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
+ auto& a = A();
auto& f = F();
switch (x) {
case 0:
@@ -907,7 +904,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
MEMPTR().word++;
readPort();
if (y != 6) // IN r[y],(C)
- R(y) = m_memory.DATA();
+ R(y, a) = m_memory.DATA();
adjustSZPXY(f, m_memory.DATA());
clearFlag(f, NF | HC);
cycles += 12;
@@ -918,18 +915,20 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
if (y == 6) // OUT (C),0
m_memory.placeDATA(0);
else // OUT (C),r[y]
- m_memory.placeDATA(R(y));
+ m_memory.placeDATA(R(y, a));
writePort();
cycles += 12;
break;
case 2: // 16-bit add/subtract with carry
switch (q) {
case 0: // SBC HL, rp[p]
- sbcViaMemptr(HL2(), RP(p));
+ sbc(f, HL2(), RP(p));
break;
case 1: // ADC HL, rp[p]
- adcViaMemptr(HL2(), RP(p));
+ adc(f, HL2(), RP(p));
break;
+ default:
+ __assume(0);
}
cycles += 15;
break;
@@ -943,11 +942,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
fetchWord();
getWordViaMemptr(RP(p));
break;
+ default:
+ __assume(0);
}
cycles += 20;
break;
case 4: // Negate accumulator
- neg();
+ neg(a, f);
cycles += 8;
break;
case 5: // Return from interrupt
@@ -978,47 +979,54 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
case 1:
case 5:
IM() = 0;
+ break;
+ default:
+ __assume(0);
}
cycles += 8;
break;
case 7: // Assorted ops
switch (y) {
case 0: // LD I,A
- IV() = A();
+ IV() = a;
cycles += 9;
break;
case 1: // LD R,A
- REFRESH() = A();
+ REFRESH() = a;
cycles += 9;
break;
case 2: // LD A,I
- A() = IV();
- adjustSZXY(f, A());
- setFlag(f, PF, IFF2());
+ a = IV();
+ adjustSZXY(f, a);
clearFlag(f, NF | HC);
+ setFlag(f, PF, IFF2());
cycles += 9;
break;
case 3: // LD A,R
- A() = REFRESH();
- adjustSZXY(f, A());
+ a = REFRESH();
+ adjustSZXY(f, a);
clearFlag(f, NF | HC);
setFlag(f, PF, IFF2());
cycles += 9;
break;
case 4: // RRD
- rrd();
+ rrd(a, f);
cycles += 18;
break;
case 5: // RLD
- rld();
+ rld(a, f);
cycles += 18;
break;
case 6: // NOP
case 7: // NOP
cycles += 4;
break;
+ default:
+ __assume(0);
}
break;
+ default:
+ __assume(0);
}
break;
case 2:
@@ -1026,19 +1034,19 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
case 0: // LD
switch (y) {
case 4: // LDI
- ldi();
+ ldi(a, f);
break;
case 5: // LDD
- ldd();
+ ldd(a, f);
break;
case 6: // LDIR
- if (ldir()) {
+ if (ldir(a, f)) {
PC().word -= 2;
cycles += 5;
}
break;
case 7: // LDDR
- if (lddr()) {
+ if (lddr(a, f)) {
PC().word -= 2;
cycles += 5;
}
@@ -1048,19 +1056,19 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
case 1: // CP
switch (y) {
case 4: // CPI
- cpi();
+ cpi(a, f);
break;
case 5: // CPD
- cpd();
+ cpd(a, f);
break;
case 6: // CPIR
- if (cpir()) {
+ if (cpir(a, f)) {
PC().word -= 2;
cycles += 5;
}
break;
case 7: // CPDR
- if (cpdr()) {
+ if (cpdr(a, f)) {
PC().word -= 2;
cycles += 5;
}
@@ -1070,19 +1078,19 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
case 2: // IN
switch (y) {
case 4: // INI
- ini();
+ ini(f);
break;
case 5: // IND
- ind();
+ ind(f);
break;
case 6: // INIR
- if (inir()) {
+ if (inir(f)) {
PC().word -= 2;
cycles += 5;
}
break;
case 7: // INDR
- if (indr()) {
+ if (indr(f)) {
PC().word -= 2;
cycles += 5;
}
@@ -1092,19 +1100,19 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
case 3: // OUT
switch (y) {
case 4: // OUTI
- outi();
+ outi(f);
break;
case 5: // OUTD
- outd();
+ outd(f);
break;
case 6: // OTIR
- if (otir()) {
+ if (otir(f)) {
PC().word -= 2;
cycles += 5;
}
break;
case 7: // OTDR
- if (otdr()) {
+ if (otdr(f)) {
PC().word -= 2;
cycles += 5;
}
@@ -1118,6 +1126,7 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
}
void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
+ auto& a = A();
auto& f = F();
switch (x) {
case 0:
@@ -1141,7 +1150,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 12;
break;
default: // JR cc,d
- if (jrConditionalFlag(y - 4))
+ if (jrConditionalFlag(f, y - 4))
cycles += 5;
cycles += 5;
break;
@@ -1150,13 +1159,15 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1: // 16-bit load immediate/add
switch (q) {
case 0: // LD rp,nn
- Processor::fetchWord(RP(p));
+ fetchWord(RP(p));
cycles += 10;
break;
case 1: // ADD HL,rp
- addViaMemptr(HL2(), RP(p));
+ add(f, HL2(), RP(p));
cycles += 11;
break;
+ default:
+ __assume(0);
}
break;
case 2: // Indirect loading
@@ -1165,12 +1176,12 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
switch (p) {
case 0: // LD (BC),A
MEMPTR() = BC();
- MEMPTR().high = memptrReference() = A();
+ MEMPTR().high = memptrReference() = a;
cycles += 7;
break;
case 1: // LD (DE),A
MEMPTR() = DE();
- MEMPTR().high = memptrReference() = A();
+ MEMPTR().high = memptrReference() = a;
cycles += 7;
break;
case 2: // LD (nn),HL
@@ -1180,21 +1191,23 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
break;
case 3: // LD (nn),A
fetchWord();
- MEMPTR().high = memptrReference() = A();
+ MEMPTR().high = memptrReference() = a;
cycles += 13;
break;
+ default:
+ __assume(0);
}
break;
case 1:
switch (p) {
case 0: // LD A,(BC)
MEMPTR() = BC();
- A() = memptrReference();
+ a = memptrReference();
cycles += 7;
break;
case 1: // LD A,(DE)
MEMPTR() = DE();
- A() = memptrReference();
+ a = memptrReference();
cycles += 7;
break;
case 2: // LD HL,(nn)
@@ -1204,11 +1217,15 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
break;
case 3: // LD A,(nn)
fetchWord();
- A() = memptrReference();
+ a = memptrReference();
cycles += 13;
break;
+ default:
+ __assume(0);
}
break;
+ default:
+ __assume(0);
}
break;
case 3: // 16-bit INC/DEC
@@ -1219,21 +1236,23 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 1: // DEC rp
--RP(p).word;
break;
+ default:
+ __assume(0);
}
cycles += 6;
break;
case 4: // 8-bit INC
- postIncrement(f, ++R(y)); // INC r
+ postIncrement(f, ++R(y, a)); // INC r
cycles += 4;
break;
case 5: // 8-bit DEC
- postDecrement(f, --R(y)); // DEC r
+ postDecrement(f, --R(y, a)); // DEC r
cycles += 4;
if (y == 6)
cycles += 7;
break;
case 6: { // 8-bit load immediate
- auto& r = R(y); // LD r,n
+ auto& r = R(y, a); // LD r,n
r = fetchByte();
cycles += 7;
if (y == 6)
@@ -1242,32 +1261,36 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
} case 7: // Assorted operations on accumulator/flags
switch (y) {
case 0:
- rlc(A());
+ rlc(f, a);
break;
case 1:
- rrc(A());
+ rrc(f, a);
break;
case 2:
- rl(A());
+ rl(f, a);
break;
case 3:
- rr(A());
+ rr(f, a);
break;
case 4:
- daa();
+ daa(a, f);
break;
case 5:
- cpl();
+ cpl(a, f);
break;
case 6:
- scf();
+ scf(a, f);
break;
case 7:
- ccf();
+ ccf(a, f);
break;
+ default:
+ __assume(0);
}
cycles += 4;
break;
+ default:
+ __assume(0);
}
break;
case 1: // 8-bit loading
@@ -1279,11 +1302,11 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
if (z == 6) {
switch (y) {
case 4:
- H() = R(z);
+ H() = R(z, a);
normal = false;
break;
case 5:
- L() = R(z);
+ L() = R(z, a);
normal = false;
break;
}
@@ -1291,18 +1314,18 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
if (y == 6) {
switch (z) {
case 4:
- R(y) = H();
+ R(y, a) = H();
normal = false;
break;
case 5:
- R(y) = L();
+ R(y, a) = L();
normal = false;
break;
}
}
}
if (normal)
- R(y) = R(z);
+ R(y, a) = R(z, a);
if ((y == 6) || (z == 6)) // M operations
cycles += 3;
}
@@ -1311,29 +1334,31 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 2: // Operate on accumulator and register/memory location
switch (y) {
case 0: // ADD A,r
- add(A(), R(z));
+ add(f, a, R(z, a));
break;
case 1: // ADC A,r
- adc(A(), R(z));
+ adc(f, a, R(z, a));
break;
case 2: // SUB r
- sub(A(), R(z));
+ sub(f, a, R(z, a));
break;
case 3: // SBC A,r
- sbc(A(), R(z));
+ sbc(f, a, R(z, a));
break;
case 4: // AND r
- andr(A(), R(z));
+ andr(f, a, R(z, a));
break;
case 5: // XOR r
- xorr(A(), R(z));
+ xorr(f, a, R(z, a));
break;
case 6: // OR r
- orr(A(), R(z));
+ orr(f, a, R(z, a));
break;
case 7: // CP r
- compare(R(z));
+ compare(f, a, R(z, a));
break;
+ default:
+ __assume(0);
}
cycles += 4;
if (z == 6)
@@ -1342,7 +1367,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 3:
switch (z) {
case 0: // Conditional return
- if (returnConditionalFlag(y))
+ if (returnConditionalFlag(f, y))
cycles += 6;
cycles += 5;
break;
@@ -1370,11 +1395,16 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
SP() = HL2();
cycles += 4;
break;
+ default:
+ __assume(0);
}
+ break;
+ default:
+ __assume(0);
}
break;
case 2: // Conditional jump
- jumpConditionalFlag(y);
+ jumpConditionalFlag(f, y);
cycles += 10;
break;
case 3: // Assorted operations
@@ -1391,25 +1421,15 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
fetchExecute();
break;
case 2: // OUT (n),A
- m_memory.ADDRESS().low = fetchByte();
- m_memory.ADDRESS().high = A();
- MEMPTR() = m_memory.ADDRESS();
- m_memory.placeDATA(A());
- writePort();
- MEMPTR().low++;
+ writePort(fetchByte(), a);
cycles += 11;
break;
case 3: // IN A,(n)
- m_memory.ADDRESS().low = fetchByte();
- m_memory.ADDRESS().high = A();
- MEMPTR() = m_memory.ADDRESS();
- readPort();
- A() = m_memory.DATA();
- MEMPTR().low++;
+ readPort(fetchByte(), a);
cycles += 11;
break;
case 4: // EX (SP),HL
- xhtl();
+ xhtl(HL2());
cycles += 19;
break;
case 5: // EX DE,HL
@@ -1424,10 +1444,12 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
ei();
cycles += 4;
break;
+ default:
+ __assume(0);
}
break;
case 4: // Conditional call: CALL cc[y], nn
- if (callConditionalFlag(y))
+ if (callConditionalFlag(f, y))
cycles += 7;
cycles += 10;
break;
@@ -1456,35 +1478,42 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
m_displaced = m_prefixFD = true;
fetchExecute();
break;
+ default:
+ __assume(0);
}
+ break;
+ default:
+ __assume(0);
}
break;
case 6: // Operate on accumulator and immediate operand: alu[y] n
switch (y) {
case 0: // ADD A,n
- add(A(), fetchByte());
+ add(f, a, fetchByte());
break;
case 1: // ADC A,n
- adc(A(), fetchByte());
+ adc(f, a, fetchByte());
break;
case 2: // SUB n
- sub(A(), fetchByte());
+ sub(f, a, fetchByte());
break;
case 3: // SBC A,n
- sbc(A(), fetchByte());
+ sbc(f, a, fetchByte());
break;
case 4: // AND n
- andr(A(), fetchByte());
+ andr(f, a, fetchByte());
break;
case 5: // XOR n
- xorr(A(), fetchByte());
+ xorr(f, a, fetchByte());
break;
case 6: // OR n
- orr(A(), fetchByte());
+ orr(f, a, fetchByte());
break;
case 7: // CP n
- compare(fetchByte());
+ compare(f, a, fetchByte());
break;
+ default:
+ __assume(0);
}
cycles += 7;
break;
@@ -1492,6 +1521,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
restart(y << 3);
cycles += 11;
break;
+ default:
+ __assume(0);
}
break;
}
diff --git a/Z80/src/Z80.vcxproj b/Z80/src/Z80.vcxproj
index f43ea30..3fb7c70 100644
--- a/Z80/src/Z80.vcxproj
+++ b/Z80/src/Z80.vcxproj
@@ -23,7 +23,6 @@
{01974F81-2750-45AF-B845-2C903A54A334}
Win32Proj
Z80
- 8.1
diff --git a/Z80/src/stdafx.h b/Z80/src/stdafx.h
index fe79e2d..ef248a1 100644
--- a/Z80/src/stdafx.h
+++ b/Z80/src/stdafx.h
@@ -19,24 +19,3 @@
#include
#include
-
-//#include
-//#include
-//
-//#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
diff --git a/Z80/test/Board.h b/Z80/test/Board.h
index dfb4eaf..0c7c4be 100644
--- a/Z80/test/Board.h
+++ b/Z80/test/Board.h
@@ -14,9 +14,8 @@ 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; }
+ EightBit::Memory& Memory() { return m_memory; }
+ EightBit::Z80& CPU() { return m_cpu; }
void initialise();
diff --git a/Z80/test/test_Z80.vcxproj b/Z80/test/test_Z80.vcxproj
index c215a2b..f61a03a 100644
--- a/Z80/test/test_Z80.vcxproj
+++ b/Z80/test/test_Z80.vcxproj
@@ -84,6 +84,7 @@
..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)
C:\local\boost_1_64_0\lib64-msvc-14.0;$(LibraryPath)
+ false
diff --git a/inc/AddressEventArgs.h b/inc/AddressEventArgs.h
new file mode 100644
index 0000000..ef1e036
--- /dev/null
+++ b/inc/AddressEventArgs.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include
+
+namespace EightBit {
+ class AddressEventArgs {
+ private:
+ uint16_t m_address;
+ uint8_t m_cell;
+
+ public:
+ AddressEventArgs(uint16_t address, uint8_t cell)
+ : m_address(address), m_cell(cell) {}
+
+ uint16_t getAddress() const { return m_address; }
+ uint8_t getCell() const { return m_cell; }
+ };
+}
\ No newline at end of file
diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h
index d6fe05d..2fda28c 100644
--- a/inc/IntelProcessor.h
+++ b/inc/IntelProcessor.h
@@ -13,6 +13,8 @@ namespace EightBit {
virtual void initialise();
+ register16_t& SP() { return sp; }
+
virtual register16_t& AF() = 0;
uint8_t& A() { return AF().high; }
uint8_t& F() { return AF().low; }
@@ -32,19 +34,6 @@ namespace EightBit {
protected:
IntelProcessor(Memory& memory);
- static void clearFlag(uint8_t& f, int flag) { f &= ~flag; }
- static void setFlag(uint8_t& f, 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 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); }
-
- //
-
template static void adjustSign(uint8_t& f, uint8_t value) {
setFlag(f, T::SF, value & T::SF);
}
@@ -54,7 +43,7 @@ namespace EightBit {
}
template static void adjustParity(uint8_t& f, 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 };
+ static const int 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(f, T::PF, set % 2);
}
@@ -87,27 +76,40 @@ namespace EightBit {
//
static int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) {
+ __assume(calculation < 0x1ffff);
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
}
static bool calculateHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
+ __assume(calculation < 0x1ffff);
static std::array m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
auto index = buildHalfCarryIndex(before, value, calculation);
return m_halfCarryTableAdd[index & Mask3];
}
static bool calculateHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
+ __assume(calculation < 0x1ffff);
std::array m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
auto index = buildHalfCarryIndex(before, value, calculation);
return m_halfCarryTableSub[index & Mask3];
}
+ uint8_t fetchByte() {
+ m_memory.ADDRESS().word = PC().word++;
+ return m_memory.reference();
+ }
+
+ void fetchWord(register16_t& output) {
+ output.low = fetchByte();
+ output.high = fetchByte();
+ }
+
void push(uint8_t value) {
m_memory.ADDRESS().word = --SP().word;
m_memory.reference() = value;
}
- void pushWord(register16_t value) {
+ void pushWord(const register16_t& value) {
push(value.high);
push(value.low);
}
@@ -123,7 +125,7 @@ namespace EightBit {
}
void fetchWord() {
- Processor::fetchWord(MEMPTR());
+ fetchWord(MEMPTR());
}
//
@@ -202,5 +204,6 @@ namespace EightBit {
private:
register16_t m_memptr;
+ register16_t sp;
};
}
\ No newline at end of file
diff --git a/inc/Memory.h b/inc/Memory.h
index a10f90e..685f474 100644
--- a/inc/Memory.h
+++ b/inc/Memory.h
@@ -4,6 +4,9 @@
#include
#include
+#include "Signal.h"
+#include "AddressEventArgs.h"
+
#if defined(_M_X64) || defined(_M_IX86 )
# define HOST_LITTLE_ENDIAN
#else
@@ -29,26 +32,23 @@ namespace EightBit {
class Memory {
public:
- static uint8_t highByte(uint16_t value) {
- return value >> 8;
- }
-
- static uint8_t lowByte(uint16_t value) {
- return value & 0xff;
- }
-
Memory(uint16_t addressMask);
+ virtual ~Memory();
- virtual register16_t& ADDRESS() { return m_address; }
- virtual uint8_t& DATA() { return *m_data; }
+ // Only fired with read/write methods
+ Signal WrittenByte;
+ Signal ReadByte;
- virtual uint8_t& placeDATA(uint8_t value) {
+ register16_t& ADDRESS() { return m_address; }
+ uint8_t& DATA() { return *m_data; }
+
+ uint8_t& placeDATA(uint8_t value) {
m_temporary = value;
m_data = &m_temporary;
return DATA();
}
- virtual uint8_t& referenceDATA(uint8_t& value) {
+ uint8_t& referenceDATA(uint8_t& value) {
m_data = &value;
return DATA();
}
@@ -61,10 +61,39 @@ namespace EightBit {
return m_locked[effective] ? placeDATA(m_bus[effective]) : referenceDATA(m_bus[effective]);
}
- virtual uint16_t effectiveAddress(uint16_t address) const {
+ virtual int effectiveAddress(int address) const {
return address & m_addressMask;
}
+ void fireReadBusEvent() {
+ ReadByte.fire(AddressEventArgs(ADDRESS().word, DATA()));
+ }
+
+ uint8_t read() {
+ auto content = reference();
+ fireReadBusEvent();
+ return content;
+ }
+
+ uint8_t read(uint16_t offset) {
+ ADDRESS().word = offset;
+ return read();
+ }
+
+ void fireWriteBusEvent() {
+ WrittenByte.fire(AddressEventArgs(ADDRESS().word, DATA()));
+ }
+
+ void write(uint8_t value) {
+ reference() = value;
+ fireWriteBusEvent();
+ }
+
+ void write(uint16_t offset, uint8_t value) {
+ ADDRESS().word = offset;
+ write(value);
+ }
+
void clear();
void loadRom(const std::string& path, uint16_t offset);
void loadRam(const std::string& path, uint16_t offset);
diff --git a/inc/Processor.h b/inc/Processor.h
index 7c1da28..abd7641 100644
--- a/inc/Processor.h
+++ b/inc/Processor.h
@@ -38,16 +38,15 @@ namespace EightBit {
Bit0 = 0x1,
};
- static uint8_t highNibble(uint8_t value) { return value >> 4; }
- static uint8_t lowNibble(uint8_t value) { return value & Mask4; }
+ static int highNibble(int value) { return value >> 4; }
+ static int lowNibble(int value) { return value & Mask4; }
- static uint8_t promoteNibble(uint8_t value) { return value << 4; }
- static uint8_t demoteNibble(uint8_t value) { return highNibble(value); }
+ static int promoteNibble(int value) { return value << 4; }
+ static int demoteNibble(int value) { return highNibble(value); }
const Memory& getMemory() const { return m_memory; }
register16_t& PC() { return pc; }
- register16_t& SP() { return sp; }
bool isHalted() const { return m_halted; }
void halt() { --PC().word; m_halted = true; }
@@ -57,24 +56,24 @@ namespace EightBit {
void reset();
protected:
+ static void clearFlag(uint8_t& f, int flag) { f &= ~flag; }
+ static void setFlag(uint8_t& f, 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 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); }
+
Processor(Memory& memory);
Memory& m_memory;
int cycles;
- uint8_t fetchByte() {
- m_memory.ADDRESS().word = PC().word++;
- return m_memory.reference();
- }
-
- void fetchWord(register16_t& output) {
- output.low = fetchByte();
- output.high = fetchByte();
- }
-
private:
register16_t pc;
- register16_t sp;
bool m_halted;
};
}
\ No newline at end of file
diff --git a/inc/TestHarness.h b/inc/TestHarness.h
index 885f6ca..2d5667c 100644
--- a/inc/TestHarness.h
+++ b/inc/TestHarness.h
@@ -1,46 +1,66 @@
#pragma once
#include
+#include
+#include
namespace EightBit {
template class TestHarness {
public:
TestHarness(const ConfigurationT& configuration)
- : m_configuration(configuration),
- m_board(configuration) {
+ : m_board(configuration),
+ m_totalCycles(0),
+ m_instructions(0),
+ m_startHostCycles(0),
+ m_finishHostCycles(0) {
}
~TestHarness() {
- std::cout << std::endl;
+ std::cout << std::dec << std::endl;
std::cout.imbue(std::locale(""));
- std::cout << "Cycles = " << m_totalCycles << std::endl;
+ std::cout << "Guest cycles = " << m_totalCycles << std::endl;
std::cout << "Seconds = " << getElapsedSeconds() << std::endl;
- std::cout << getCyclesPerSecond() << " cycles/second" << std::endl;
+ std::cout << getCyclesPerSecond() << " MHz" << std::endl;
+ std::cout << getInstructionsPerSecond() << " instructions per second" << std::endl;
+
+ auto elapsedHostCycles = m_finishHostCycles - m_startHostCycles;
+ std::cout << "Host cycles = " << elapsedHostCycles << std::endl;
+
+ auto efficiency = elapsedHostCycles / m_totalCycles;
+ std::cout << "Efficiency = " << efficiency << std::endl;
}
std::chrono::steady_clock::duration getElapsedTime() const {
return m_finishTime - m_startTime;
}
- long long getElapsedSeconds() const {
- return std::chrono::duration_cast(getElapsedTime()).count();
+ double getElapsedSeconds() const {
+ return std::chrono::duration_cast>(getElapsedTime()).count();
}
- long long getCyclesPerSecond() const {
- return m_totalCycles / getElapsedSeconds();
+ double getCyclesPerSecond() const {
+ return (m_totalCycles / 1000000 ) / getElapsedSeconds();
+ }
+
+ long long getInstructionsPerSecond() {
+ auto floating = m_instructions / getElapsedSeconds();
+ return (long long)floating;
}
void runLoop() {
m_startTime = now();
- m_totalCycles = 0UL;
+ m_totalCycles = m_instructions = 0L;
+ m_startHostCycles = currentHostCycles();
- auto& cpu = m_board.getCPUMutable();
+ auto& cpu = m_board.CPU();
while (!cpu.isHalted()) {
m_totalCycles += cpu.step();
+ ++m_instructions;
}
+ m_finishHostCycles = currentHostCycles();
m_finishTime = now();
}
@@ -49,14 +69,20 @@ namespace EightBit {
}
private:
- const ConfigurationT& m_configuration;
BoardT m_board;
long long m_totalCycles;
+ long long m_instructions;
std::chrono::steady_clock::time_point m_startTime;
std::chrono::steady_clock::time_point m_finishTime;
+ unsigned __int64 m_startHostCycles;
+ unsigned __int64 m_finishHostCycles;
- std::chrono::steady_clock::time_point now() {
+ static std::chrono::steady_clock::time_point now() {
return std::chrono::steady_clock::now();
}
+
+ static unsigned __int64 currentHostCycles() {
+ return __rdtsc();
+ }
};
}
\ No newline at end of file
diff --git a/src/EightBit.vcxproj b/src/EightBit.vcxproj
index 2e34973..2532ba8 100644
--- a/src/EightBit.vcxproj
+++ b/src/EightBit.vcxproj
@@ -138,6 +138,7 @@
+
diff --git a/src/EightBit.vcxproj.filters b/src/EightBit.vcxproj.filters
index bf1e258..57c17c6 100644
--- a/src/EightBit.vcxproj.filters
+++ b/src/EightBit.vcxproj.filters
@@ -32,6 +32,9 @@
Header Files
+
+ Header Files
+
diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp
index 5f89687..042bffc 100644
--- a/src/IntelProcessor.cpp
+++ b/src/IntelProcessor.cpp
@@ -4,9 +4,11 @@
EightBit::IntelProcessor::IntelProcessor(Memory& memory)
: Processor(memory) {
MEMPTR().word = 0;
+ SP().word = 0xffff;
}
void EightBit::IntelProcessor::initialise() {
Processor::initialise();
MEMPTR().word = 0;
+ SP().word = 0xffff;
}
diff --git a/src/Memory.cpp b/src/Memory.cpp
index 29c3d5b..060a711 100644
--- a/src/Memory.cpp
+++ b/src/Memory.cpp
@@ -14,6 +14,9 @@ EightBit::Memory::Memory(uint16_t addressMask)
m_data = &(m_bus[m_address.word]);
}
+EightBit::Memory::~Memory() {
+}
+
uint8_t EightBit::Memory::peek(uint16_t address) const {
return m_bus[address];
}
diff --git a/src/Processor.cpp b/src/Processor.cpp
index 5a177c6..19d952d 100644
--- a/src/Processor.cpp
+++ b/src/Processor.cpp
@@ -5,7 +5,6 @@ EightBit::Processor::Processor(Memory& memory)
: m_memory(memory),
cycles(0),
m_halted(false) {
- SP().word = 0xffff;
PC().word = 0;
}
@@ -14,6 +13,5 @@ void EightBit::Processor::reset() {
}
void EightBit::Processor::initialise() {
- SP().word = 0xffff;
reset();
}