mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-09-11 16:24:35 +00:00
Improve the flexibility of the BUS mapping/read/write architecture.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
@@ -27,7 +27,7 @@ namespace EightBit {
|
|||||||
Signal<Intel8080> ExecutingInstruction;
|
Signal<Intel8080> ExecutingInstruction;
|
||||||
Signal<Intel8080> ExecutedInstruction;
|
Signal<Intel8080> ExecutedInstruction;
|
||||||
|
|
||||||
virtual int execute(uint8_t opcode) final;
|
virtual int execute() final;
|
||||||
virtual int step() final;
|
virtual int step() final;
|
||||||
|
|
||||||
virtual register16_t& AF() final;
|
virtual register16_t& AF() final;
|
||||||
|
@@ -35,7 +35,7 @@ void EightBit::Intel8080::handleINT() {
|
|||||||
raise(HALT());
|
raise(HALT());
|
||||||
if (m_interruptEnable) {
|
if (m_interruptEnable) {
|
||||||
di();
|
di();
|
||||||
execute(BUS().DATA());
|
Processor::execute(BUS().DATA());
|
||||||
}
|
}
|
||||||
addCycles(3);
|
addCycles(3);
|
||||||
}
|
}
|
||||||
@@ -275,18 +275,18 @@ int EightBit::Intel8080::step() {
|
|||||||
} else if (UNLIKELY(lowered(INT()))) {
|
} else if (UNLIKELY(lowered(INT()))) {
|
||||||
handleINT();
|
handleINT();
|
||||||
} else if (UNLIKELY(lowered(HALT()))) {
|
} else if (UNLIKELY(lowered(HALT()))) {
|
||||||
execute(0); // NOP
|
Processor::execute(0); // NOP
|
||||||
} else {
|
} else {
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExecutedInstruction.fire(*this);
|
ExecutedInstruction.fire(*this);
|
||||||
return cycles();
|
return cycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
int EightBit::Intel8080::execute(const uint8_t opcode) {
|
int EightBit::Intel8080::execute() {
|
||||||
|
|
||||||
const auto& decoded = getDecodedOpcode(opcode);
|
const auto& decoded = getDecodedOpcode(opcode());
|
||||||
|
|
||||||
const auto x = decoded.x;
|
const auto x = decoded.x;
|
||||||
const auto y = decoded.y;
|
const auto y = decoded.y;
|
||||||
|
@@ -36,7 +36,7 @@ namespace EightBit {
|
|||||||
virtual register16_t& HL() final;
|
virtual register16_t& HL() final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int execute(uint8_t opcode) final;
|
virtual int execute() final;
|
||||||
virtual int step() final;
|
virtual int step() final;
|
||||||
|
|
||||||
virtual void handleRESET() final;
|
virtual void handleRESET() final;
|
||||||
|
@@ -326,9 +326,9 @@ int EightBit::GameBoy::LR35902::step() {
|
|||||||
} else if (UNLIKELY(lowered(INT()))) {
|
} else if (UNLIKELY(lowered(INT()))) {
|
||||||
handleINT();
|
handleINT();
|
||||||
} else if (UNLIKELY(lowered(HALT()))) {
|
} else if (UNLIKELY(lowered(HALT()))) {
|
||||||
execute(0); // NOP
|
Processor::execute(0); // NOP
|
||||||
} else {
|
} else {
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bus.IO().checkTimers(clockCycles());
|
m_bus.IO().checkTimers(clockCycles());
|
||||||
@@ -339,9 +339,9 @@ int EightBit::GameBoy::LR35902::step() {
|
|||||||
return clockCycles();
|
return clockCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
int EightBit::GameBoy::LR35902::execute(const uint8_t opcode) {
|
int EightBit::GameBoy::LR35902::execute() {
|
||||||
|
|
||||||
const auto& decoded = getDecodedOpcode(opcode);
|
const auto& decoded = getDecodedOpcode(opcode());
|
||||||
|
|
||||||
const auto x = decoded.x;
|
const auto x = decoded.x;
|
||||||
const auto y = decoded.y;
|
const auto y = decoded.y;
|
||||||
@@ -750,7 +750,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
|
|||||||
break;
|
break;
|
||||||
case 1: // CB prefix
|
case 1: // CB prefix
|
||||||
m_prefixCB = true;
|
m_prefixCB = true;
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
break;
|
break;
|
||||||
case 6: // DI
|
case 6: // DI
|
||||||
di();
|
di();
|
||||||
|
@@ -57,7 +57,7 @@ namespace EightBit {
|
|||||||
Signal<mc6809> ExecutingInstruction;
|
Signal<mc6809> ExecutingInstruction;
|
||||||
Signal<mc6809> ExecutedInstruction;
|
Signal<mc6809> ExecutedInstruction;
|
||||||
|
|
||||||
virtual int execute(uint8_t opcode) final;
|
virtual int execute() final;
|
||||||
virtual int step() final;
|
virtual int step() final;
|
||||||
|
|
||||||
virtual void powerOn() final;
|
virtual void powerOn() final;
|
||||||
@@ -148,9 +148,9 @@ namespace EightBit {
|
|||||||
|
|
||||||
// Execution helpers
|
// Execution helpers
|
||||||
|
|
||||||
void executeUnprefixed(uint8_t opcode);
|
void executeUnprefixed();
|
||||||
void execute10(uint8_t opcode);
|
void execute10();
|
||||||
void execute11(uint8_t opcode);
|
void execute11();
|
||||||
|
|
||||||
// Register selection for "indexed"
|
// Register selection for "indexed"
|
||||||
register16_t& RR(int which);
|
register16_t& RR(int which);
|
||||||
|
@@ -29,7 +29,7 @@ int EightBit::mc6809::step() {
|
|||||||
else if (UNLIKELY(lowered(IRQ()) && !interruptMasked()))
|
else if (UNLIKELY(lowered(IRQ()) && !interruptMasked()))
|
||||||
handleIRQ();
|
handleIRQ();
|
||||||
else
|
else
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
}
|
}
|
||||||
ExecutedInstruction.fire(*this);
|
ExecutedInstruction.fire(*this);
|
||||||
return cycles();
|
return cycles();
|
||||||
@@ -88,32 +88,32 @@ void EightBit::mc6809::handleFIRQ() {
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
int EightBit::mc6809::execute(const uint8_t opcode) {
|
int EightBit::mc6809::execute() {
|
||||||
lower(BA());
|
lower(BA());
|
||||||
lower(BS());
|
lower(BS());
|
||||||
const bool prefixed = m_prefix10 || m_prefix11;
|
const bool prefixed = m_prefix10 || m_prefix11;
|
||||||
const bool unprefixed = !prefixed;
|
const bool unprefixed = !prefixed;
|
||||||
if (unprefixed) {
|
if (unprefixed) {
|
||||||
executeUnprefixed(opcode);
|
executeUnprefixed();
|
||||||
} else {
|
} else {
|
||||||
if (m_prefix10)
|
if (m_prefix10)
|
||||||
execute10(opcode);
|
execute10();
|
||||||
else
|
else
|
||||||
execute11(opcode);
|
execute11();
|
||||||
}
|
}
|
||||||
assert(cycles() > 0);
|
assert(cycles() > 0);
|
||||||
return cycles();
|
return cycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::mc6809::executeUnprefixed(const uint8_t opcode) {
|
void EightBit::mc6809::executeUnprefixed() {
|
||||||
|
|
||||||
assert(!(m_prefix10 || m_prefix11));
|
assert(!(m_prefix10 || m_prefix11));
|
||||||
assert(cycles() == 0);
|
assert(cycles() == 0);
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode()) {
|
||||||
|
|
||||||
case 0x10: m_prefix10 = true; execute(fetchByte()); break;
|
case 0x10: m_prefix10 = true; Processor::execute(fetchByte()); break;
|
||||||
case 0x11: m_prefix11 = true; execute(fetchByte()); break;
|
case 0x11: m_prefix11 = true; Processor::execute(fetchByte()); break;
|
||||||
|
|
||||||
// ABX
|
// ABX
|
||||||
case 0x3a: addCycles(3); X() += B(); break; // ABX (inherent)
|
case 0x3a: addCycles(3); X() += B(); break; // ABX (inherent)
|
||||||
@@ -475,12 +475,12 @@ void EightBit::mc6809::executeUnprefixed(const uint8_t opcode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::mc6809::execute10(const uint8_t opcode) {
|
void EightBit::mc6809::execute10() {
|
||||||
|
|
||||||
assert(m_prefix10 && !m_prefix11);
|
assert(m_prefix10 && !m_prefix11);
|
||||||
assert(cycles() == 0);
|
assert(cycles() == 0);
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode()) {
|
||||||
|
|
||||||
// CMP
|
// CMP
|
||||||
|
|
||||||
@@ -546,12 +546,12 @@ void EightBit::mc6809::execute10(const uint8_t opcode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::mc6809::execute11(const uint8_t opcode) {
|
void EightBit::mc6809::execute11() {
|
||||||
|
|
||||||
assert(!m_prefix10 && m_prefix11);
|
assert(!m_prefix10 && m_prefix11);
|
||||||
assert(cycles() == 0);
|
assert(cycles() == 0);
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode()) {
|
||||||
|
|
||||||
// CMP
|
// CMP
|
||||||
|
|
||||||
|
@@ -54,7 +54,7 @@ namespace EightBit {
|
|||||||
[[nodiscard]] auto& NMI() { return m_nmiLine; } // In
|
[[nodiscard]] auto& NMI() { return m_nmiLine; } // In
|
||||||
[[nodiscard]] auto& M1() { return m_m1Line; } // Out
|
[[nodiscard]] auto& M1() { return m_m1Line; } // Out
|
||||||
|
|
||||||
int execute(uint8_t opcode) final;
|
int execute() final;
|
||||||
int step() final;
|
int step() final;
|
||||||
void powerOn() final;
|
void powerOn() final;
|
||||||
|
|
||||||
|
@@ -67,7 +67,7 @@ void EightBit::Z80::handleINT() {
|
|||||||
di();
|
di();
|
||||||
switch (IM()) {
|
switch (IM()) {
|
||||||
case 0: // i8080 equivalent
|
case 0: // i8080 equivalent
|
||||||
execute(BUS().DATA());
|
Processor::execute(BUS().DATA());
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
restart(7 << 3);
|
restart(7 << 3);
|
||||||
@@ -671,16 +671,16 @@ int EightBit::Z80::step() {
|
|||||||
} else if (UNLIKELY(lowered(INT()))) {
|
} else if (UNLIKELY(lowered(INT()))) {
|
||||||
handleINT();
|
handleINT();
|
||||||
} else if (UNLIKELY(lowered(HALT()))) {
|
} else if (UNLIKELY(lowered(HALT()))) {
|
||||||
execute(0); // NOP
|
Processor::execute(0); // NOP
|
||||||
} else {
|
} else {
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExecutedInstruction.fire(*this);
|
ExecutedInstruction.fire(*this);
|
||||||
return cycles();
|
return cycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
int EightBit::Z80::execute(const uint8_t opcode) {
|
int EightBit::Z80::execute() {
|
||||||
|
|
||||||
ASSUME(lowered(M1()));
|
ASSUME(lowered(M1()));
|
||||||
|
|
||||||
@@ -689,7 +689,7 @@ int EightBit::Z80::execute(const uint8_t opcode) {
|
|||||||
raise(M1());
|
raise(M1());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& decoded = getDecodedOpcode(opcode);
|
const auto& decoded = getDecodedOpcode(opcode());
|
||||||
|
|
||||||
const auto x = decoded.x;
|
const auto x = decoded.x;
|
||||||
const auto y = decoded.y;
|
const auto y = decoded.y;
|
||||||
@@ -1364,7 +1364,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
|
|||||||
if (UNLIKELY(m_displaced))
|
if (UNLIKELY(m_displaced))
|
||||||
fetchDisplacement();
|
fetchDisplacement();
|
||||||
lower(M1());
|
lower(M1());
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
break;
|
break;
|
||||||
case 2: // OUT (n),A
|
case 2: // OUT (n),A
|
||||||
writePort(fetchByte());
|
writePort(fetchByte());
|
||||||
@@ -1414,17 +1414,17 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
|
|||||||
case 1: // DD prefix
|
case 1: // DD prefix
|
||||||
m_displaced = m_prefixDD = true;
|
m_displaced = m_prefixDD = true;
|
||||||
lower(M1());
|
lower(M1());
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
break;
|
break;
|
||||||
case 2: // ED prefix
|
case 2: // ED prefix
|
||||||
m_prefixED = true;
|
m_prefixED = true;
|
||||||
lower(M1());
|
lower(M1());
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
break;
|
break;
|
||||||
case 3: // FD prefix
|
case 3: // FD prefix
|
||||||
m_displaced = m_prefixFD = true;
|
m_displaced = m_prefixFD = true;
|
||||||
lower(M1());
|
lower(M1());
|
||||||
execute(fetchByte());
|
Processor::execute(fetchByte());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
|
@@ -9,10 +9,10 @@
|
|||||||
#include "Signal.h"
|
#include "Signal.h"
|
||||||
#include "Register.h"
|
#include "Register.h"
|
||||||
#include "EventArgs.h"
|
#include "EventArgs.h"
|
||||||
#include "MemoryMapping.h"
|
#include "Mapper.h"
|
||||||
|
|
||||||
namespace EightBit {
|
namespace EightBit {
|
||||||
class Bus {
|
class Bus : public Mapper {
|
||||||
public:
|
public:
|
||||||
virtual ~Bus() = default;
|
virtual ~Bus() = default;
|
||||||
|
|
||||||
@@ -54,7 +54,6 @@ namespace EightBit {
|
|||||||
protected:
|
protected:
|
||||||
virtual void initialise() = 0;
|
virtual void initialise() = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual MemoryMapping mapping(uint16_t address) = 0;
|
|
||||||
[[nodiscard]] uint8_t& reference(uint16_t address);
|
[[nodiscard]] uint8_t& reference(uint16_t address);
|
||||||
[[nodiscard]] auto& reference(const register16_t address) { return reference(address.word); }
|
[[nodiscard]] auto& reference(const register16_t address) { return reference(address.word); }
|
||||||
[[nodiscard]] uint8_t& reference() { return reference(ADDRESS()); }
|
[[nodiscard]] uint8_t& reference() { return reference(ADDRESS()); }
|
||||||
|
14
inc/Mapper.h
Normal file
14
inc/Mapper.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "MemoryMapping.h"
|
||||||
|
|
||||||
|
namespace EightBit {
|
||||||
|
class Mapper {
|
||||||
|
public:
|
||||||
|
virtual ~Mapper() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual MemoryMapping mapping(uint16_t address) = 0;
|
||||||
|
};
|
||||||
|
}
|
@@ -9,7 +9,7 @@ namespace EightBit {
|
|||||||
|
|
||||||
struct MemoryMapping {
|
struct MemoryMapping {
|
||||||
|
|
||||||
enum class AccessLevel { Unknown, ReadOnly, ReadWrite, };
|
enum class AccessLevel { Unknown, ReadOnly, WriteOnly, ReadWrite };
|
||||||
|
|
||||||
Memory& memory;
|
Memory& memory;
|
||||||
uint16_t begin = Chip::Mask16;
|
uint16_t begin = Chip::Mask16;
|
||||||
|
@@ -29,7 +29,8 @@ namespace EightBit {
|
|||||||
|
|
||||||
int run(int limit);
|
int run(int limit);
|
||||||
virtual int step() = 0;
|
virtual int step() = 0;
|
||||||
virtual int execute(uint8_t opcode) = 0;
|
virtual int execute() = 0;
|
||||||
|
int execute(uint8_t value);
|
||||||
|
|
||||||
[[nodiscard]] auto cycles() const noexcept { return m_cycles; }
|
[[nodiscard]] auto cycles() const noexcept { return m_cycles; }
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ namespace EightBit {
|
|||||||
protected:
|
protected:
|
||||||
Processor(Bus& memory);
|
Processor(Bus& memory);
|
||||||
|
|
||||||
|
[[nodiscard]] auto& opcode() noexcept { return m_opcode; }
|
||||||
[[nodiscard]] auto& BUS() noexcept { return m_bus; }
|
[[nodiscard]] auto& BUS() noexcept { return m_bus; }
|
||||||
|
|
||||||
[[nodiscard]] auto halted() noexcept { return lowered(HALT()); }
|
[[nodiscard]] auto halted() noexcept { return lowered(HALT()); }
|
||||||
@@ -49,16 +51,23 @@ namespace EightBit {
|
|||||||
virtual void handleINT();
|
virtual void handleINT();
|
||||||
virtual void handleIRQ();
|
virtual void handleIRQ();
|
||||||
|
|
||||||
|
void busWrite(register16_t address, uint8_t data);
|
||||||
|
void busWrite(uint8_t data);
|
||||||
|
virtual void busWrite();
|
||||||
|
|
||||||
|
[[nodiscard]] uint8_t busRead(register16_t address);
|
||||||
|
[[nodiscard]] virtual uint8_t busRead();
|
||||||
|
|
||||||
[[nodiscard]] auto getBytePaged(const uint8_t page, const uint8_t offset) {
|
[[nodiscard]] auto getBytePaged(const uint8_t page, const uint8_t offset) {
|
||||||
return BUS().read(register16_t(offset, page));
|
return busRead(register16_t(offset, page));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) {
|
void setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) {
|
||||||
BUS().write(register16_t(offset, page), value);
|
busWrite(register16_t(offset, page), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto fetchByte() {
|
[[nodiscard]] auto fetchByte() {
|
||||||
return BUS().read(PC()++);
|
return busRead(PC()++);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] virtual register16_t getWord() = 0;
|
[[nodiscard]] virtual register16_t getWord() = 0;
|
||||||
@@ -102,6 +111,7 @@ namespace EightBit {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Bus& m_bus;
|
Bus& m_bus;
|
||||||
|
uint8_t m_opcode = Mask8;
|
||||||
int m_cycles = 0;
|
int m_cycles = 0;
|
||||||
register16_t m_pc;
|
register16_t m_pc;
|
||||||
|
|
||||||
|
@@ -5,29 +5,29 @@ EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory)
|
|||||||
: Processor(memory) {}
|
: Processor(memory) {}
|
||||||
|
|
||||||
EightBit::register16_t EightBit::BigEndianProcessor::getWord() {
|
EightBit::register16_t EightBit::BigEndianProcessor::getWord() {
|
||||||
const auto high = BUS().read();
|
const auto high = busRead();
|
||||||
++BUS().ADDRESS();
|
++BUS().ADDRESS();
|
||||||
const auto low = BUS().read();
|
const auto low = busRead();
|
||||||
return { low, high };
|
return { low, high };
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::BigEndianProcessor::setWord(const register16_t value) {
|
void EightBit::BigEndianProcessor::setWord(const register16_t value) {
|
||||||
BUS().write(value.high);
|
busWrite(value.high);
|
||||||
++BUS().ADDRESS();
|
++BUS().ADDRESS();
|
||||||
BUS().write(value.low);
|
busWrite(value.low);
|
||||||
}
|
}
|
||||||
|
|
||||||
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
|
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
|
||||||
const auto high = getBytePaged(page, offset);
|
const auto high = getBytePaged(page, offset);
|
||||||
++BUS().ADDRESS().low;
|
++BUS().ADDRESS().low;
|
||||||
const auto low = BUS().read();
|
const auto low = busRead();
|
||||||
return { low, high };
|
return { low, high };
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
|
void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
|
||||||
setBytePaged(page, offset, value.high);
|
setBytePaged(page, offset, value.high);
|
||||||
++BUS().ADDRESS().low;
|
++BUS().ADDRESS().low;
|
||||||
BUS().write(value.low);
|
busWrite(value.low);
|
||||||
}
|
}
|
||||||
|
|
||||||
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() {
|
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() {
|
||||||
|
@@ -150,6 +150,7 @@
|
|||||||
<ClInclude Include="..\inc\InputOutput.h" />
|
<ClInclude Include="..\inc\InputOutput.h" />
|
||||||
<ClInclude Include="..\inc\IntelProcessor.h" />
|
<ClInclude Include="..\inc\IntelProcessor.h" />
|
||||||
<ClInclude Include="..\inc\LittleEndianProcessor.h" />
|
<ClInclude Include="..\inc\LittleEndianProcessor.h" />
|
||||||
|
<ClInclude Include="..\inc\Mapper.h" />
|
||||||
<ClInclude Include="..\inc\Rom.h" />
|
<ClInclude Include="..\inc\Rom.h" />
|
||||||
<ClInclude Include="..\inc\Memory.h" />
|
<ClInclude Include="..\inc\Memory.h" />
|
||||||
<ClInclude Include="..\inc\MemoryMapping.h" />
|
<ClInclude Include="..\inc\MemoryMapping.h" />
|
||||||
|
@@ -65,6 +65,9 @@
|
|||||||
<ClInclude Include="..\inc\Memory.h">
|
<ClInclude Include="..\inc\Memory.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\Mapper.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
@@ -5,29 +5,29 @@ EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory)
|
|||||||
: Processor(memory) {}
|
: Processor(memory) {}
|
||||||
|
|
||||||
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() {
|
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() {
|
||||||
const auto low = BUS().read();
|
const auto low = busRead();
|
||||||
++BUS().ADDRESS();
|
++BUS().ADDRESS();
|
||||||
const auto high = BUS().read();
|
const auto high = busRead();
|
||||||
return { low, high };
|
return { low, high };
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::LittleEndianProcessor::setWord(const register16_t value) {
|
void EightBit::LittleEndianProcessor::setWord(const register16_t value) {
|
||||||
BUS().write(value.low);
|
busWrite(value.low);
|
||||||
++BUS().ADDRESS();
|
++BUS().ADDRESS();
|
||||||
BUS().write(value.high);
|
busWrite(value.high);
|
||||||
}
|
}
|
||||||
|
|
||||||
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
|
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
|
||||||
const auto low = getBytePaged(page, offset);
|
const auto low = getBytePaged(page, offset);
|
||||||
++BUS().ADDRESS().low;
|
++BUS().ADDRESS().low;
|
||||||
const auto high = BUS().read();
|
const auto high = busRead();
|
||||||
return { low, high };
|
return { low, high };
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
|
void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
|
||||||
setBytePaged(page, offset, value.low);
|
setBytePaged(page, offset, value.low);
|
||||||
++BUS().ADDRESS().low;
|
++BUS().ADDRESS().low;
|
||||||
BUS().write(value.high);
|
busWrite(value.high);
|
||||||
}
|
}
|
||||||
|
|
||||||
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() {
|
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() {
|
||||||
|
@@ -25,6 +25,29 @@ void EightBit::Processor::handleIRQ() {
|
|||||||
raise(IRQ());
|
raise(IRQ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EightBit::Processor::busWrite(const register16_t address, const uint8_t data) {
|
||||||
|
BUS().ADDRESS() = address;
|
||||||
|
busWrite(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Processor::busWrite(const uint8_t data) {
|
||||||
|
BUS().DATA() = data;
|
||||||
|
busWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Processor::busWrite() {
|
||||||
|
BUS().write();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t EightBit::Processor::busRead(const register16_t address) {
|
||||||
|
BUS().ADDRESS() = address;
|
||||||
|
return busRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t EightBit::Processor::busRead() {
|
||||||
|
return BUS().read();
|
||||||
|
}
|
||||||
|
|
||||||
int EightBit::Processor::run(const int limit) {
|
int EightBit::Processor::run(const int limit) {
|
||||||
int current = 0;
|
int current = 0;
|
||||||
while (LIKELY(powered() && (current < limit)))
|
while (LIKELY(powered() && (current < limit)))
|
||||||
@@ -32,6 +55,11 @@ int EightBit::Processor::run(const int limit) {
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int EightBit::Processor::execute(const uint8_t value) {
|
||||||
|
opcode() = value;
|
||||||
|
return execute();
|
||||||
|
}
|
||||||
|
|
||||||
// http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
|
// http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
|
||||||
int8_t EightBit::Processor::signExtend(const int b, uint8_t x) {
|
int8_t EightBit::Processor::signExtend(const int b, uint8_t x) {
|
||||||
const uint8_t m = 1 << (b - 1); // mask can be pre-computed if b is fixed
|
const uint8_t m = 1 << (b - 1); // mask can be pre-computed if b is fixed
|
||||||
|
Reference in New Issue
Block a user