Extensive change warning: lots of "noexcept" and "constexpr" changes. Not sure if I'll keep all of them, but interesting...

Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2021-07-18 14:28:40 +01:00
parent 2f76e901f9
commit 22506ea56c
56 changed files with 561 additions and 550 deletions

View File

@ -26,8 +26,8 @@ namespace Gaming {
virtual void raisePOWER() override; virtual void raisePOWER() override;
protected: protected:
virtual float fps() const = 0; virtual float fps() const noexcept = 0;
virtual bool useVsync() const = 0; virtual bool useVsync() const noexcept = 0;
virtual int windowWidth() const noexcept; virtual int windowWidth() const noexcept;
virtual int windowHeight() const noexcept; virtual int windowHeight() const noexcept;
@ -37,7 +37,7 @@ namespace Gaming {
virtual int rasterWidth() const noexcept = 0; virtual int rasterWidth() const noexcept = 0;
virtual int rasterHeight() const noexcept = 0; virtual int rasterHeight() const noexcept = 0;
virtual std::string title() const = 0; virtual std::string title() const noexcept = 0;
virtual void handleEvents(); virtual void handleEvents();
virtual void update(); virtual void update();

View File

@ -14,6 +14,10 @@
namespace EightBit { namespace EightBit {
class Intel8080 final : public IntelProcessor { class Intel8080 final : public IntelProcessor {
public:
DECLARE_PIN_OUTPUT(DBIN) // Active high
DECLARE_PIN_OUTPUT(WR) // Active low
public: public:
enum StatusBits { enum StatusBits {
SF = Bit7, SF = Bit7,
@ -31,19 +35,16 @@ namespace EightBit {
virtual int execute() final; virtual int execute() final;
virtual int step() final; virtual int step() final;
virtual register16_t& AF() final; [[nodiscard]] virtual register16_t& AF() noexcept final;
virtual register16_t& BC() final; [[nodiscard]] virtual register16_t& BC() noexcept final;
virtual register16_t& DE() final; [[nodiscard]] virtual register16_t& DE() noexcept final;
virtual register16_t& HL() final; [[nodiscard]] virtual register16_t& HL() noexcept final;
bool requestingIO() noexcept { return m_requestIO; } [[nodiscard]] bool requestingIO() noexcept { return m_requestIO; }
bool requestingMemory() noexcept { return m_requestMemory; } [[nodiscard]] bool requestingMemory() noexcept { return m_requestMemory; }
bool requestingRead() { return raised(DBIN()); } [[nodiscard]] bool requestingRead() noexcept { return raised(DBIN()); }
bool requestingWrite() { return lowered(WR()); } [[nodiscard]] bool requestingWrite() noexcept { return lowered(WR()); }
DECLARE_PIN_OUTPUT(DBIN) // Active high
DECLARE_PIN_OUTPUT(WR) // Active low
protected: protected:
void handleRESET() final; void handleRESET() final;

View File

@ -19,20 +19,20 @@ EightBit::Intel8080::Intel8080(Bus& bus)
DEFINE_PIN_LEVEL_CHANGERS(DBIN, Intel8080); DEFINE_PIN_LEVEL_CHANGERS(DBIN, Intel8080);
DEFINE_PIN_LEVEL_CHANGERS(WR, Intel8080); DEFINE_PIN_LEVEL_CHANGERS(WR, Intel8080);
EightBit::register16_t& EightBit::Intel8080::AF() { EightBit::register16_t& EightBit::Intel8080::AF() noexcept {
af.low = (af.low | Bit1) & ~(Bit5 | Bit3); af.low = (af.low | Bit1) & ~(Bit5 | Bit3);
return af; return af;
} }
EightBit::register16_t& EightBit::Intel8080::BC() { EightBit::register16_t& EightBit::Intel8080::BC() noexcept {
return bc; return bc;
} }
EightBit::register16_t& EightBit::Intel8080::DE() { EightBit::register16_t& EightBit::Intel8080::DE() noexcept {
return de; return de;
} }
EightBit::register16_t& EightBit::Intel8080::HL() { EightBit::register16_t& EightBit::Intel8080::HL() noexcept {
return hl; return hl;
} }

View File

@ -23,7 +23,7 @@ public:
virtual void initialise() final; virtual void initialise() final;
protected: protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) final { virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite }; return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
} }

View File

@ -35,7 +35,7 @@ namespace Fuse {
EightBit::register16_t actual, EightBit::register16_t expected) const; EightBit::register16_t actual, EightBit::register16_t expected) const;
protected: protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) final { virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite }; return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
} }

View File

@ -10,9 +10,9 @@ namespace EightBit {
namespace GameBoy { namespace GameBoy {
class CharacterDefinition final { class CharacterDefinition final {
public: public:
CharacterDefinition(Ram& vram, uint16_t address); CharacterDefinition(Ram& vram, uint16_t address) noexcept;
[[nodiscard]] std::array<int, 8> get(int row) const; [[nodiscard]] std::array<int, 8> get(int row) const noexcept;
private: private:
Ram& m_vram; Ram& m_vram;

View File

@ -27,12 +27,12 @@ namespace EightBit {
PixelCount = RasterWidth * RasterHeight, PixelCount = RasterWidth * RasterHeight,
}; };
Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram); Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram) noexcept;
[[nodiscard]] const auto& pixels() const noexcept { return m_pixels; } [[nodiscard]] const auto& pixels() const noexcept { return m_pixels; }
void renderCurrentScanline(); void renderCurrentScanline() noexcept;
void loadObjectAttributes(); void loadObjectAttributes() noexcept;
private: private:
enum class tile_offset_t { enum class tile_offset_t {
@ -48,35 +48,35 @@ namespace EightBit {
uint8_t m_control = 0; uint8_t m_control = 0;
uint8_t m_scanLine = 0; uint8_t m_scanLine = 0;
[[nodiscard]] std::array<int, 4> createPalette(int address); [[nodiscard]] std::array<int, 4> createPalette(int address) noexcept;
void renderBackground(); void renderBackground() noexcept;
void renderBackground( void renderBackground(
int bgArea, int bgCharacters, int bgArea, int bgCharacters,
tile_offset_t offsetType, tile_offset_t offsetType,
int offsetX, int offsetY, int offsetX, int offsetY,
const std::array<int, 4>& palette); const std::array<int, 4>& palette) noexcept;
void renderObjects(); void renderObjects() noexcept;
void renderSpriteTile( void renderSpriteTile(
int height, int height,
int drawX, int drawY, int drawX, int drawY,
bool flipX, bool flipY, bool flipX, bool flipY,
const std::array<int, 4>& palette, const std::array<int, 4>& palette,
const CharacterDefinition& definition); const CharacterDefinition& definition) noexcept;
void renderBackgroundTile( void renderBackgroundTile(
int drawX, int drawY, int drawX, int drawY,
const std::array<int, 4>& palette, const std::array<int, 4>& palette,
const CharacterDefinition& definition); const CharacterDefinition& definition) noexcept;
void renderTile( void renderTile(
int height, int height,
int drawX, int drawY, int drawX, int drawY,
bool flipX, bool flipY, bool allowTransparencies, bool flipX, bool flipY, bool allowTransparencies,
const std::array<int, 4>& palette, const std::array<int, 4>& palette,
const CharacterDefinition& definition); const CharacterDefinition& definition) noexcept;
}; };
} }
} }

View File

@ -59,7 +59,7 @@ namespace EightBit {
void runVerticalBlankLines(); void runVerticalBlankLines();
protected: protected:
virtual MemoryMapping mapping(uint16_t address) override; virtual MemoryMapping mapping(uint16_t address) noexcept override;
private: private:
LR35902 m_cpu; LR35902 m_cpu;
@ -94,7 +94,7 @@ namespace EightBit {
void validateCartridgeType(); void validateCartridgeType();
void Bus_WrittenByte(EightBit::EventArgs); void Bus_WrittenByte(EightBit::EventArgs) noexcept;
void runRasterLines(int lines); void runRasterLines(int lines);
void runVerticalBlankLines(int lines); void runVerticalBlankLines(int lines);

View File

@ -26,16 +26,16 @@ namespace EightBit {
Signal<LR35902> ExecutingInstruction; Signal<LR35902> ExecutingInstruction;
Signal<LR35902> ExecutedInstruction; Signal<LR35902> ExecutedInstruction;
[[nodiscard]] register16_t& AF() final; [[nodiscard]] register16_t& AF() noexcept final;
[[nodiscard]] register16_t& BC() final; [[nodiscard]] register16_t& BC() noexcept final;
[[nodiscard]] register16_t& DE() final; [[nodiscard]] register16_t& DE() noexcept final;
[[nodiscard]] register16_t& HL() final; [[nodiscard]] register16_t& HL() noexcept final;
bool& IME() noexcept { return m_ime; } bool& IME() noexcept { return m_ime; }
[[nodiscard]] uint8_t enabledInterrupts(); [[nodiscard]] uint8_t enabledInterrupts() noexcept;
[[nodiscard]] uint8_t flaggedInterrupts(); [[nodiscard]] uint8_t flaggedInterrupts() noexcept;
[[nodiscard]] uint8_t maskedInterrupts(); [[nodiscard]] uint8_t maskedInterrupts() noexcept;
Signal<EventArgs> MachineTicked; Signal<EventArgs> MachineTicked;
@ -76,33 +76,33 @@ namespace EightBit {
[[nodiscard]] uint8_t R(int r); [[nodiscard]] uint8_t R(int r);
void R(int r, uint8_t value); void R(int r, uint8_t value);
[[nodiscard]] register16_t& RP(int rp); [[nodiscard]] register16_t& RP(int rp) noexcept;
[[nodiscard]] register16_t& RP2(int rp); [[nodiscard]] register16_t& RP2(int rp) noexcept;
[[nodiscard]] static auto adjustHalfCarryAdd(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) { [[nodiscard]] static constexpr auto adjustHalfCarryAdd(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation)); return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
} }
[[nodiscard]] static auto adjustHalfCarrySub(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) { [[nodiscard]] static constexpr auto adjustHalfCarrySub(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation)); return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
} }
[[nodiscard]] static bool convertCondition(uint8_t f, int flag); [[nodiscard]] static bool convertCondition(uint8_t f, int flag) noexcept;
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0); static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
void executeCB(int x, int y, int z, int p, int q); void executeCB(int x, int y, int z, int p, int q);
void executeOther(int x, int y, int z, int p, int q); void executeOther(int x, int y, int z, int p, int q);
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand) noexcept;
void stop(bool value = true) noexcept { m_stopped = value; } void stop(bool value = true) noexcept { m_stopped = value; }
void start() noexcept { stop(false); } void start() noexcept { stop(false); }
[[nodiscard]] bool stopped() const noexcept { return m_stopped; } [[nodiscard]] bool stopped() const noexcept { return m_stopped; }
void di(); void di() noexcept;
void ei(); void ei() noexcept;
void reti(); void reti();
@ -113,33 +113,33 @@ namespace EightBit {
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value); [[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value);
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0); [[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value); static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static void compare(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
static void bit(uint8_t& f, int n, uint8_t operand); static void bit(uint8_t& f, int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t res(int n, uint8_t operand); [[nodiscard]] static uint8_t res(int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t set(int n, uint8_t operand); [[nodiscard]] static uint8_t set(int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand) noexcept;
static void scf(uint8_t& f, uint8_t operand); static void scf(uint8_t& f, uint8_t operand) noexcept;
static void ccf(uint8_t& f, uint8_t operand); static void ccf(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t swap(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t swap(uint8_t& f, uint8_t operand) noexcept;
}; };
} }
} }

View File

@ -3,12 +3,12 @@
#include <Ram.h> #include <Ram.h>
EightBit::GameBoy::CharacterDefinition::CharacterDefinition(Ram& vram, const uint16_t address) EightBit::GameBoy::CharacterDefinition::CharacterDefinition(Ram& vram, const uint16_t address) noexcept
: m_vram(vram), : m_vram(vram),
m_address(address) { m_address(address) {
} }
std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) const { std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) const noexcept {
std::array<int, 8> returned; std::array<int, 8> returned;

View File

@ -7,14 +7,14 @@
#include <Processor.h> #include <Processor.h>
EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram) EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram) noexcept
: m_bus(bus), : m_bus(bus),
m_oam(oam), m_oam(oam),
m_vram(vram), m_vram(vram),
m_colours(colours) { m_colours(colours) {
} }
void EightBit::GameBoy::Display::renderCurrentScanline() { void EightBit::GameBoy::Display::renderCurrentScanline() noexcept {
m_scanLine = m_bus.IO().peek(IoRegisters::LY); m_scanLine = m_bus.IO().peek(IoRegisters::LY);
if (m_scanLine < RasterHeight) { if (m_scanLine < RasterHeight) {
m_control = m_bus.IO().peek(IoRegisters::LCDC); m_control = m_bus.IO().peek(IoRegisters::LCDC);
@ -26,7 +26,7 @@ void EightBit::GameBoy::Display::renderCurrentScanline() {
} }
} }
std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address) { std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address) noexcept {
const auto raw = m_bus.IO().peek(address); const auto raw = m_bus.IO().peek(address);
const std::array<int, 4> palette = { const std::array<int, 4> palette = {
raw & 0b11, raw & 0b11,
@ -37,12 +37,12 @@ std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address)
return palette; return palette;
} }
void EightBit::GameBoy::Display::loadObjectAttributes() { void EightBit::GameBoy::Display::loadObjectAttributes() noexcept {
for (int i = 0; i < 40; ++i) for (int i = 0; i < 40; ++i)
m_objectAttributes[i] = ObjectAttribute(m_oam, 4 * i); m_objectAttributes[i] = ObjectAttribute(m_oam, 4 * i);
} }
void EightBit::GameBoy::Display::renderObjects() { void EightBit::GameBoy::Display::renderObjects() noexcept {
const auto objBlockHeight = (m_control & IoRegisters::OBJ_SIZE) ? 16 : 8; const auto objBlockHeight = (m_control & IoRegisters::OBJ_SIZE) ? 16 : 8;
@ -81,7 +81,7 @@ void EightBit::GameBoy::Display::renderObjects() {
} }
} }
void EightBit::GameBoy::Display::renderBackground() { void EightBit::GameBoy::Display::renderBackground() noexcept {
const auto palette = createPalette(IoRegisters::BGP); const auto palette = createPalette(IoRegisters::BGP);
@ -105,7 +105,7 @@ void EightBit::GameBoy::Display::renderBackground() {
void EightBit::GameBoy::Display::renderBackground( void EightBit::GameBoy::Display::renderBackground(
int bgArea, int bgCharacters, tile_offset_t offsetType, int bgArea, int bgCharacters, tile_offset_t offsetType,
int offsetX, int offsetY, int offsetX, int offsetY,
const std::array<int, 4>& palette) { const std::array<int, 4>& palette) noexcept {
const int row = (m_scanLine - offsetY) / 8; const int row = (m_scanLine - offsetY) / 8;
auto address = bgArea + row * BufferCharacterWidth; auto address = bgArea + row * BufferCharacterWidth;
@ -128,7 +128,7 @@ void EightBit::GameBoy::Display::renderSpriteTile(
const int drawX, const int drawY, const int drawX, const int drawY,
const bool flipX, const bool flipY, const bool flipX, const bool flipY,
const std::array<int, 4>& palette, const std::array<int, 4>& palette,
const CharacterDefinition& definition) { const CharacterDefinition& definition) noexcept {
renderTile( renderTile(
height, height,
drawX, drawY, drawX, drawY,
@ -140,7 +140,7 @@ void EightBit::GameBoy::Display::renderSpriteTile(
void EightBit::GameBoy::Display::renderBackgroundTile( void EightBit::GameBoy::Display::renderBackgroundTile(
const int drawX, const int drawY, const int drawX, const int drawY,
const std::array<int, 4>& palette, const std::array<int, 4>& palette,
const CharacterDefinition& definition) { const CharacterDefinition& definition) noexcept {
renderTile( renderTile(
8, 8,
drawX, drawY, drawX, drawY,
@ -154,7 +154,7 @@ void EightBit::GameBoy::Display::renderTile(
const int drawX, const int drawY, const int drawX, const int drawY,
const bool flipX, const bool flipY, const bool allowTransparencies, const bool flipX, const bool flipY, const bool allowTransparencies,
const std::array<int, 4>& palette, const std::array<int, 4>& palette,
const CharacterDefinition& definition) { const CharacterDefinition& definition) noexcept {
const auto width = 8; const auto width = 8;

View File

@ -40,7 +40,7 @@ void EightBit::GameBoy::Bus::loadGameRom(const std::string path) {
validateCartridgeType(); validateCartridgeType();
} }
void EightBit::GameBoy::Bus::Bus_WrittenByte(EightBit::EventArgs) { void EightBit::GameBoy::Bus::Bus_WrittenByte(EightBit::EventArgs) noexcept {
const auto address = ADDRESS().word; const auto address = ADDRESS().word;
const auto value = DATA(); const auto value = DATA();
@ -161,7 +161,7 @@ void EightBit::GameBoy::Bus::validateCartridgeType() {
} }
} }
EightBit::MemoryMapping EightBit::GameBoy::Bus::mapping(uint16_t address) { EightBit::MemoryMapping EightBit::GameBoy::Bus::mapping(uint16_t address) noexcept {
if ((address < 0x100) && IO().bootRomEnabled()) if ((address < 0x100) && IO().bootRomEnabled())
return { m_bootRom, 0x0000, 0xffff, MemoryMapping::AccessLevel::ReadOnly }; return { m_bootRom, 0x0000, 0xffff, MemoryMapping::AccessLevel::ReadOnly };

View File

@ -13,20 +13,20 @@ EightBit::GameBoy::LR35902::LR35902(Bus& memory)
}); });
} }
EightBit::register16_t& EightBit::GameBoy::LR35902::AF() { EightBit::register16_t& EightBit::GameBoy::LR35902::AF() noexcept {
af.low = higherNibble(af.low); af.low = higherNibble(af.low);
return af; return af;
} }
EightBit::register16_t& EightBit::GameBoy::LR35902::BC() { EightBit::register16_t& EightBit::GameBoy::LR35902::BC() noexcept {
return bc; return bc;
} }
EightBit::register16_t& EightBit::GameBoy::LR35902::DE() { EightBit::register16_t& EightBit::GameBoy::LR35902::DE() noexcept {
return de; return de;
} }
EightBit::register16_t& EightBit::GameBoy::LR35902::HL() { EightBit::register16_t& EightBit::GameBoy::LR35902::HL() noexcept {
return hl; return hl;
} }
@ -87,15 +87,15 @@ void EightBit::GameBoy::LR35902::ret() {
tickMachine(); tickMachine();
} }
void EightBit::GameBoy::LR35902::di() { void EightBit::GameBoy::LR35902::di() noexcept {
IME() = false; IME() = false;
} }
void EightBit::GameBoy::LR35902::ei() { void EightBit::GameBoy::LR35902::ei() noexcept {
IME() = true; IME() = true;
} }
uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF); f = clearBit(f, NF);
const uint8_t result = operand + 1; const uint8_t result = operand + 1;
f = adjustZero<LR35902>(f, result); f = adjustZero<LR35902>(f, result);
@ -103,7 +103,7 @@ uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand)
return result; return result;
} }
uint8_t EightBit::GameBoy::LR35902::decrement(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::decrement(uint8_t& f, const uint8_t operand) noexcept {
f = setBit(f, NF); f = setBit(f, NF);
f = clearBit(f, HC, lowNibble(operand)); f = clearBit(f, HC, lowNibble(operand));
const uint8_t result = operand - 1; const uint8_t result = operand - 1;
@ -165,7 +165,7 @@ void EightBit::GameBoy::LR35902::R(const int r, const uint8_t value) {
} }
} }
EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) { EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) noexcept {
switch (rp) { switch (rp) {
case 0b00: case 0b00:
return BC(); return BC();
@ -180,7 +180,7 @@ EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) {
} }
} }
EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) { EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) noexcept {
switch (rp) { switch (rp) {
case 0b00: case 0b00:
return BC(); return BC();
@ -195,7 +195,7 @@ EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) {
} }
} }
bool EightBit::GameBoy::LR35902::convertCondition(const uint8_t f, int flag) { bool EightBit::GameBoy::LR35902::convertCondition(const uint8_t f, int flag) noexcept {
ASSUME(flag >= 0); ASSUME(flag >= 0);
ASSUME(flag <= 7); ASSUME(flag <= 7);
switch (flag) { switch (flag) {
@ -249,7 +249,7 @@ EightBit::register16_t EightBit::GameBoy::LR35902::add(uint8_t& f, const registe
return result; return result;
} }
uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) { uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
const register16_t addition = operand + value + carry; const register16_t addition = operand + value + carry;
const auto result = addition.low; const auto result = addition.low;
@ -263,11 +263,11 @@ uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const
return result; return result;
} }
uint8_t EightBit::GameBoy::LR35902::adc(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::GameBoy::LR35902::adc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
return add(f, operand, value, (f & CF) >> 4); return add(f, operand, value, (f & CF) >> 4);
} }
uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) { uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
const register16_t subtraction = operand - value - carry; const register16_t subtraction = operand - value - carry;
const auto result = subtraction.low; const auto result = subtraction.low;
@ -281,11 +281,11 @@ uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand,
return result; return result;
} }
uint8_t EightBit::GameBoy::LR35902::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::GameBoy::LR35902::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
return subtract(f, operand, value, (f & CF) >> 4); return subtract(f, operand, value, (f & CF) >> 4);
} }
uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
f = setBit(f, HC); f = setBit(f, HC);
f = clearBit(f, CF | NF); f = clearBit(f, CF | NF);
const uint8_t result = operand & value; const uint8_t result = operand & value;
@ -293,76 +293,76 @@ uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, cons
return result; return result;
} }
uint8_t EightBit::GameBoy::LR35902::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::GameBoy::LR35902::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
f = clearBit(f, HC | CF | NF); f = clearBit(f, HC | CF | NF);
const uint8_t result = operand ^ value; const uint8_t result = operand ^ value;
f = adjustZero<LR35902>(f, result); f = adjustZero<LR35902>(f, result);
return result; return result;
} }
uint8_t EightBit::GameBoy::LR35902::orr(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::GameBoy::LR35902::orr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
f = clearBit(f, HC | CF | NF); f = clearBit(f, HC | CF | NF);
const uint8_t result = operand | value; const uint8_t result = operand | value;
f = adjustZero<LR35902>(f, result); f = adjustZero<LR35902>(f, result);
return result; return result;
} }
void EightBit::GameBoy::LR35902::compare(uint8_t& f, uint8_t operand, const uint8_t value) { void EightBit::GameBoy::LR35902::compare(uint8_t& f, uint8_t operand, const uint8_t value) noexcept {
subtract(f, operand, value); subtract(f, operand, value);
} }
uint8_t EightBit::GameBoy::LR35902::rlc(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::rlc(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | ZF); f = clearBit(f, NF | HC | ZF);
const auto carry = operand & Bit7; const auto carry = operand & Bit7;
f = setBit(f, CF, carry); f = setBit(f, CF, carry);
return (operand << 1) | (carry >> 7); return (operand << 1) | (carry >> 7);
} }
uint8_t EightBit::GameBoy::LR35902::rrc(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::rrc(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | ZF); f = clearBit(f, NF | HC | ZF);
const auto carry = operand & Bit0; const auto carry = operand & Bit0;
f = setBit(f, CF, carry); f = setBit(f, CF, carry);
return (operand >> 1) | (carry << 7); return (operand >> 1) | (carry << 7);
} }
uint8_t EightBit::GameBoy::LR35902::rl(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::rl(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | ZF); f = clearBit(f, NF | HC | ZF);
const auto carry = f & CF; const auto carry = f & CF;
f = setBit(f, CF, operand & Bit7); f = setBit(f, CF, operand & Bit7);
return (operand << 1) | (carry >> 4); // CF at Bit4 return (operand << 1) | (carry >> 4); // CF at Bit4
} }
uint8_t EightBit::GameBoy::LR35902::rr(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::rr(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | ZF); f = clearBit(f, NF | HC | ZF);
const auto carry = f & CF; const auto carry = f & CF;
f = setBit(f, CF, operand & Bit0); f = setBit(f, CF, operand & Bit0);
return (operand >> 1) | (carry << 3); // CF at Bit4 return (operand >> 1) | (carry << 3); // CF at Bit4
} }
uint8_t EightBit::GameBoy::LR35902::sla(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::sla(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | ZF); f = clearBit(f, NF | HC | ZF);
f = setBit(f, CF, operand & Bit7); f = setBit(f, CF, operand & Bit7);
return operand << 1; return operand << 1;
} }
uint8_t EightBit::GameBoy::LR35902::sra(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::sra(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | ZF); f = clearBit(f, NF | HC | ZF);
f = setBit(f, CF, operand & Bit0); f = setBit(f, CF, operand & Bit0);
return (operand >> 1) | (operand & Bit7); return (operand >> 1) | (operand & Bit7);
} }
uint8_t EightBit::GameBoy::LR35902::swap(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::swap(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | CF); f = clearBit(f, NF | HC | CF);
return promoteNibble(operand) | demoteNibble(operand); return promoteNibble(operand) | demoteNibble(operand);
} }
uint8_t EightBit::GameBoy::LR35902::srl(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::srl(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC | ZF); f = clearBit(f, NF | HC | ZF);
f = setBit(f, CF, operand & Bit0); f = setBit(f, CF, operand & Bit0);
return (operand >> 1) & ~Bit7; return (operand >> 1) & ~Bit7;
} }
void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t operand) { void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t operand) noexcept {
ASSUME(n >= 0); ASSUME(n >= 0);
ASSUME(n <= 7); ASSUME(n <= 7);
const auto carry = f & CF; const auto carry = f & CF;
@ -370,19 +370,19 @@ void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t oper
f = setBit(f, CF, carry); f = setBit(f, CF, carry);
} }
uint8_t EightBit::GameBoy::LR35902::res(const int n, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::res(const int n, const uint8_t operand) noexcept {
ASSUME(n >= 0); ASSUME(n >= 0);
ASSUME(n <= 7); ASSUME(n <= 7);
return clearBit(operand, Chip::bit(n)); return clearBit(operand, Chip::bit(n));
} }
uint8_t EightBit::GameBoy::LR35902::set(const int n, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::set(const int n, const uint8_t operand) noexcept {
ASSUME(n >= 0); ASSUME(n >= 0);
ASSUME(n <= 7); ASSUME(n <= 7);
return setBit(operand, Chip::bit(n)); return setBit(operand, Chip::bit(n));
} }
uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) noexcept {
int updated = operand; int updated = operand;
@ -407,30 +407,30 @@ uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::GameBoy::LR35902::cpl(uint8_t& f, const uint8_t operand) { uint8_t EightBit::GameBoy::LR35902::cpl(uint8_t& f, const uint8_t operand) noexcept {
f = setBit(f, HC | NF); f = setBit(f, HC | NF);
return ~operand; return ~operand;
} }
void EightBit::GameBoy::LR35902::scf(uint8_t& f, const uint8_t operand) { void EightBit::GameBoy::LR35902::scf(uint8_t& f, const uint8_t operand) noexcept {
f = setBit(f, CF); f = setBit(f, CF);
f = clearBit(f, HC | NF); f = clearBit(f, HC | NF);
} }
void EightBit::GameBoy::LR35902::ccf(uint8_t& f, const uint8_t operand) { void EightBit::GameBoy::LR35902::ccf(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
f = clearBit(f, CF, f & CF); f = clearBit(f, CF, f & CF);
} }
uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() { uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() noexcept {
return BUS().peek(IoRegisters::BASE + IoRegisters::IE); return BUS().peek(IoRegisters::BASE + IoRegisters::IE);
} }
uint8_t EightBit::GameBoy::LR35902::flaggedInterrupts() { uint8_t EightBit::GameBoy::LR35902::flaggedInterrupts() noexcept {
return m_bus.IO().peek(IoRegisters::IF); return m_bus.IO().peek(IoRegisters::IF);
} }
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() { uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() noexcept {
return enabledInterrupts() & flaggedInterrupts(); return enabledInterrupts() & flaggedInterrupts();
} }

View File

@ -34,13 +34,13 @@ namespace EightBit {
int execute() final; int execute() final;
[[nodiscard]] int step() final; [[nodiscard]] int step() final;
[[nodiscard]] auto& X() { return x; } [[nodiscard]] constexpr auto& X() noexcept { return x; }
[[nodiscard]] auto& Y() { return y; } [[nodiscard]] constexpr auto& Y() noexcept { return y; }
[[nodiscard]] auto& A() { return a; } [[nodiscard]] constexpr auto& A() noexcept { return a; }
[[nodiscard]] auto& S() { return s; } [[nodiscard]] constexpr auto& S() noexcept { return s; }
[[nodiscard]] auto& P() { return p; } [[nodiscard]] constexpr auto& P() noexcept { return p; }
[[nodiscard]] const auto& P() const { return p; } [[nodiscard]] constexpr const auto& P() const noexcept { return p; }
DECLARE_PIN_INPUT(NMI) DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_INPUT(SO) DECLARE_PIN_INPUT(SO)
@ -55,15 +55,15 @@ namespace EightBit {
void busWrite() final; void busWrite() final;
[[nodiscard]] uint8_t busRead() final; [[nodiscard]] uint8_t busRead() final;
[[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0); [[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0) noexcept;
[[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow); [[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow) noexcept;
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow); [[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow) noexcept;
[[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0); [[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0) noexcept;
[[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry); [[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry) noexcept;
[[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry); [[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry) noexcept;
private: private:
const uint8_t IRQvector = 0xfe; // IRQ vector const uint8_t IRQvector = 0xfe; // IRQ vector
@ -111,29 +111,29 @@ namespace EightBit {
// Flag adjustment // Flag adjustment
void adjustZero(const uint8_t datum) { P() = clearBit(P(), ZF, datum); } void adjustZero(const uint8_t datum) noexcept { P() = clearBit(P(), ZF, datum); }
void adjustNegative(const uint8_t datum) { P() = setBit(P(), NF, datum & NF); } void adjustNegative(const uint8_t datum) noexcept { P() = setBit(P(), NF, datum & NF); }
void adjustNZ(const uint8_t datum) { void adjustNZ(const uint8_t datum) noexcept {
adjustZero(datum); adjustZero(datum);
adjustNegative(datum); adjustNegative(datum);
} }
// Flag checking // Flag checking
[[nodiscard]] auto interruptMasked() const { return P() & IF; } [[nodiscard]] auto interruptMasked() const noexcept { return P() & IF; }
[[nodiscard]] auto decimal() const { return P() & DF; } [[nodiscard]] auto decimal() const noexcept { return P() & DF; }
[[nodiscard]] auto negative() const { return P() & NF; } [[nodiscard]] auto negative() const noexcept { return P() & NF; }
[[nodiscard]] auto zero() const { return P() & ZF; } [[nodiscard]] auto zero() const noexcept { return P() & ZF; }
[[nodiscard]] auto overflow() const { return P() & VF; } [[nodiscard]] auto overflow() const noexcept { return P() & VF; }
[[nodiscard]] auto carry() const { return P() & CF; } [[nodiscard]] auto carry() const noexcept { return P() & CF; }
// Miscellaneous // Miscellaneous
void branch(int condition); void branch(int condition);
[[nodiscard]] auto through(const uint8_t data) { [[nodiscard]] auto through(const uint8_t data) noexcept {
adjustNZ(data); adjustNZ(data);
return data; return data;
} }
@ -146,29 +146,29 @@ namespace EightBit {
// Instruction implementations // Instruction implementations
[[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t asl(uint8_t value); [[nodiscard]] uint8_t asl(uint8_t value) noexcept;
void bit(uint8_t operand, uint8_t data); void bit(uint8_t operand, uint8_t data) noexcept;
void cmp(uint8_t first, uint8_t second); void cmp(uint8_t first, uint8_t second) noexcept;
[[nodiscard]] uint8_t dec(uint8_t value); [[nodiscard]] uint8_t dec(uint8_t value) noexcept;
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t inc(uint8_t value); [[nodiscard]] uint8_t inc(uint8_t value) noexcept;
void jsr(); void jsr();
[[nodiscard]] uint8_t lsr(uint8_t value); [[nodiscard]] uint8_t lsr(uint8_t value) noexcept;
[[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data); [[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data) noexcept;
void php(); void php();
void plp(); void plp();
[[nodiscard]] uint8_t rol(uint8_t operand); [[nodiscard]] uint8_t rol(uint8_t operand) noexcept;
[[nodiscard]] uint8_t ror(uint8_t operand); [[nodiscard]] uint8_t ror(uint8_t operand) noexcept;
void rti(); void rti();
void rts(); void rts();
// Undocumented compound instructions // Undocumented compound instructions
void anc(uint8_t value); void anc(uint8_t value) noexcept;
void arr(uint8_t value); void arr(uint8_t value) noexcept;
void asr(uint8_t value); void asr(uint8_t value) noexcept;
void axs(uint8_t value); void axs(uint8_t value) noexcept;
void dcp(uint8_t value); void dcp(uint8_t value);
void isb(uint8_t value); void isb(uint8_t value);
void rla(uint8_t value); void rla(uint8_t value);

View File

@ -437,17 +437,15 @@ uint8_t EightBit::MOS6502::Address_ZeroPageY() {
} }
std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_AbsoluteX() { std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_AbsoluteX() {
auto address = Address_Absolute(); const auto address = Address_Absolute();
const auto page = address.high; const auto page = address.high;
address += X(); return { address + X(), page };
return { address, page };
} }
std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_AbsoluteY() { std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_AbsoluteY() {
auto address = Address_Absolute(); const auto address = Address_Absolute();
const auto page = address.high; const auto page = address.high;
address += Y(); return { address + Y(), page };
return { address, page };
} }
EightBit::register16_t EightBit::MOS6502::Address_IndexedIndirectX() { EightBit::register16_t EightBit::MOS6502::Address_IndexedIndirectX() {
@ -455,10 +453,9 @@ EightBit::register16_t EightBit::MOS6502::Address_IndexedIndirectX() {
} }
std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_IndirectIndexedY() { std::pair<EightBit::register16_t, uint8_t> EightBit::MOS6502::Address_IndirectIndexedY() {
auto address = Address_ZeroPageIndirect(); const auto address = Address_ZeroPageIndirect();
const auto page = address.high; const auto page = address.high;
address += Y(); return { address + Y(), page };
return { address, page };
} }
EightBit::register16_t EightBit::MOS6502::Address_relative_byte() { EightBit::register16_t EightBit::MOS6502::Address_relative_byte() {
@ -488,7 +485,7 @@ uint8_t EightBit::MOS6502::AM_AbsoluteX(const PageCrossingBehavior behaviour) {
} }
uint8_t EightBit::MOS6502::AM_AbsoluteY() { uint8_t EightBit::MOS6502::AM_AbsoluteY() {
const auto[address, page] = Address_AbsoluteY(); const auto [address, page] = Address_AbsoluteY();
auto possible = getBytePaged(page, address.low); auto possible = getBytePaged(page, address.low);
if (UNLIKELY(page != address.high)) if (UNLIKELY(page != address.high))
possible = memoryRead(address); possible = memoryRead(address);
@ -524,13 +521,13 @@ void EightBit::MOS6502::branch(const int condition) {
const auto page = PC().high; const auto page = PC().high;
jump(destination); jump(destination);
if (UNLIKELY(PC().high != page)) if (UNLIKELY(PC().high != page))
memoryRead(register16_t(PC().low, page)); getBytePaged(page, PC().low);
} }
} }
//// ////
uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) { uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) noexcept {
const auto returned = sub(operand, data, ~P() & CF); const auto returned = sub(operand, data, ~P() & CF);
@ -542,16 +539,16 @@ uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) {
return returned; return returned;
} }
uint8_t EightBit::MOS6502::sub(const uint8_t operand, const uint8_t data, const int borrow) { uint8_t EightBit::MOS6502::sub(const uint8_t operand, const uint8_t data, const int borrow) noexcept {
return decimal() ? sub_d(operand, data, borrow) : sub_b(operand, data, borrow); return decimal() ? sub_d(operand, data, borrow) : sub_b(operand, data, borrow);
} }
uint8_t EightBit::MOS6502::sub_b(const uint8_t operand, const uint8_t data, const int borrow) { uint8_t EightBit::MOS6502::sub_b(const uint8_t operand, const uint8_t data, const int borrow) noexcept {
m_intermediate.word = operand - data - borrow; m_intermediate.word = operand - data - borrow;
return m_intermediate.low; return m_intermediate.low;
} }
uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, const int borrow) { uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, const int borrow) noexcept {
m_intermediate.word = operand - data - borrow; m_intermediate.word = operand - data - borrow;
uint8_t low = lowNibble(operand) - lowNibble(data) - borrow; uint8_t low = lowNibble(operand) - lowNibble(data) - borrow;
@ -567,17 +564,17 @@ uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, cons
return promoteNibble(high) | lowNibble(low); return promoteNibble(high) | lowNibble(low);
} }
uint8_t EightBit::MOS6502::adc(const uint8_t operand, const uint8_t data) { uint8_t EightBit::MOS6502::adc(const uint8_t operand, const uint8_t data) noexcept {
const auto returned = add(operand, data, carry()); const auto returned = add(operand, data, carry());
adjustNZ(m_intermediate.low); adjustNZ(m_intermediate.low);
return returned; return returned;
} }
uint8_t EightBit::MOS6502::add(uint8_t operand, uint8_t data, int carry) { uint8_t EightBit::MOS6502::add(uint8_t operand, uint8_t data, int carry) noexcept {
return decimal() ? add_d(operand, data, carry) : add_b(operand, data, carry); return decimal() ? add_d(operand, data, carry) : add_b(operand, data, carry);
} }
uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carry) { uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carry) noexcept {
m_intermediate.word = operand + data + carry; m_intermediate.word = operand + data + carry;
P() = setBit(P(), VF, ~(operand ^ data) & (operand ^ m_intermediate.low) & NF); P() = setBit(P(), VF, ~(operand ^ data) & (operand ^ m_intermediate.low) & NF);
@ -586,7 +583,7 @@ uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carry) {
return m_intermediate.low; return m_intermediate.low;
} }
uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) { uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) noexcept {
m_intermediate.word = operand + data + carry; m_intermediate.word = operand + data + carry;
@ -605,36 +602,36 @@ uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) {
return promoteNibble(high) | lowNibble(low); return promoteNibble(high) | lowNibble(low);
} }
uint8_t EightBit::MOS6502::andr(const uint8_t operand, const uint8_t data) { uint8_t EightBit::MOS6502::andr(const uint8_t operand, const uint8_t data) noexcept {
return through(operand & data); return through(operand & data);
} }
uint8_t EightBit::MOS6502::asl(const uint8_t value) { uint8_t EightBit::MOS6502::asl(const uint8_t value) noexcept {
P() = setBit(P(), CF, value & Bit7); P() = setBit(P(), CF, value & Bit7);
return through(value << 1); return through(value << 1);
} }
void EightBit::MOS6502::bit(const uint8_t operand, const uint8_t data) { void EightBit::MOS6502::bit(const uint8_t operand, const uint8_t data) noexcept {
P() = setBit(P(), VF, data & VF); P() = setBit(P(), VF, data & VF);
adjustZero(operand & data); adjustZero(operand & data);
adjustNegative(data); adjustNegative(data);
} }
void EightBit::MOS6502::cmp(const uint8_t first, const uint8_t second) { void EightBit::MOS6502::cmp(const uint8_t first, const uint8_t second) noexcept {
const register16_t result = first - second; const register16_t result = first - second;
adjustNZ(result.low); adjustNZ(result.low);
P() = clearBit(P(), CF, result.high); P() = clearBit(P(), CF, result.high);
} }
uint8_t EightBit::MOS6502::dec(const uint8_t value) { uint8_t EightBit::MOS6502::dec(const uint8_t value) noexcept {
return through(value - 1); return through(value - 1);
} }
uint8_t EightBit::MOS6502::eorr(const uint8_t operand, const uint8_t data) { uint8_t EightBit::MOS6502::eorr(const uint8_t operand, const uint8_t data) noexcept {
return through(operand ^ data); return through(operand ^ data);
} }
uint8_t EightBit::MOS6502::inc(const uint8_t value) { uint8_t EightBit::MOS6502::inc(const uint8_t value) noexcept {
return through(value + 1); return through(value + 1);
} }
@ -646,12 +643,12 @@ void EightBit::MOS6502::jsr() {
PC().low = low; PC().low = low;
} }
uint8_t EightBit::MOS6502::lsr(const uint8_t value) { uint8_t EightBit::MOS6502::lsr(const uint8_t value) noexcept {
P() = setBit(P(), CF, value & Bit0); P() = setBit(P(), CF, value & Bit0);
return through(value >> 1); return through(value >> 1);
} }
uint8_t EightBit::MOS6502::orr(const uint8_t operand, const uint8_t data) { uint8_t EightBit::MOS6502::orr(const uint8_t operand, const uint8_t data) noexcept {
return through(operand | data); return through(operand | data);
} }
@ -663,14 +660,14 @@ void EightBit::MOS6502::plp() {
P() = (pop() | RF) & ~BF; P() = (pop() | RF) & ~BF;
} }
uint8_t EightBit::MOS6502::rol(const uint8_t operand) { uint8_t EightBit::MOS6502::rol(const uint8_t operand) noexcept {
const auto carryIn = carry(); const auto carryIn = carry();
P() = setBit(P(), CF, operand & Bit7); P() = setBit(P(), CF, operand & Bit7);
const uint8_t result = (operand << 1) | carryIn; const uint8_t result = (operand << 1) | carryIn;
return through(result); return through(result);
} }
uint8_t EightBit::MOS6502::ror(const uint8_t operand) { uint8_t EightBit::MOS6502::ror(const uint8_t operand) noexcept {
const auto carryIn = carry(); const auto carryIn = carry();
P() = setBit(P(), CF, operand & Bit0); P() = setBit(P(), CF, operand & Bit0);
const uint8_t result = (operand >> 1) | (carryIn << 7); const uint8_t result = (operand >> 1) | (carryIn << 7);
@ -691,24 +688,24 @@ void EightBit::MOS6502::rts() {
// Undocumented compound instructions // Undocumented compound instructions
void EightBit::MOS6502::anc(const uint8_t value) { void EightBit::MOS6502::anc(const uint8_t value) noexcept {
A() = andr(A(), value); A() = andr(A(), value);
P() = setBit(P(), CF, A() & Bit7); P() = setBit(P(), CF, A() & Bit7);
} }
void EightBit::MOS6502::arr(const uint8_t value) { void EightBit::MOS6502::arr(const uint8_t value) noexcept {
A() = andr(A(), value); A() = andr(A(), value);
A() = ror(A()); A() = ror(A());
P() = setBit(P(), CF, A() & Bit6); P() = setBit(P(), CF, A() & Bit6);
P() = setBit(P(), VF, ((A() & Bit6) >> 6) ^((A() & Bit5) >> 5)); P() = setBit(P(), VF, ((A() & Bit6) >> 6) ^((A() & Bit5) >> 5));
} }
void EightBit::MOS6502::asr(const uint8_t value) { void EightBit::MOS6502::asr(const uint8_t value) noexcept {
A() = andr(A(), value); A() = andr(A(), value);
A() = lsr(A()); A() = lsr(A());
} }
void EightBit::MOS6502::axs(const uint8_t value) { void EightBit::MOS6502::axs(const uint8_t value) noexcept {
X() = through(sub(A() & X(), value)); X() = through(sub(A() & X(), value));
P() = clearBit(P(), CF, m_intermediate.high); P() = clearBit(P(), CF, m_intermediate.high);
} }

View File

@ -23,7 +23,7 @@ public:
virtual void initialise() final; virtual void initialise() final;
protected: protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) final { virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite }; return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
} }

View File

@ -13,6 +13,14 @@
namespace EightBit { namespace EightBit {
class mc6809 : public BigEndianProcessor { class mc6809 : public BigEndianProcessor {
public:
DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_INPUT(FIRQ)
DECLARE_PIN_INPUT(HALT)
DECLARE_PIN_OUTPUT(BA)
DECLARE_PIN_OUTPUT(BS)
DECLARE_PIN_OUTPUT(RW)
public: public:
enum StatusBits { enum StatusBits {
@ -89,13 +97,6 @@ namespace EightBit {
void halt() noexcept { --PC(); lowerHALT(); } void halt() noexcept { --PC(); lowerHALT(); }
void proceed() noexcept { ++PC(); raiseHALT(); } void proceed() noexcept { ++PC(); raiseHALT(); }
DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_INPUT(FIRQ)
DECLARE_PIN_INPUT(HALT)
DECLARE_PIN_OUTPUT(BA)
DECLARE_PIN_OUTPUT(BS)
DECLARE_PIN_OUTPUT(RW)
protected: protected:
// Default push/pop handlers // Default push/pop handlers

View File

@ -111,7 +111,7 @@ void Board::initialise() {
} }
} }
EightBit::MemoryMapping Board::mapping(uint16_t address) { EightBit::MemoryMapping Board::mapping(uint16_t address) noexcept {
if (address < 0x8000) if (address < 0x8000)
return { m_ram, 0x0000, EightBit::Chip::Mask16, EightBit::MemoryMapping::AccessLevel::ReadWrite }; return { m_ram, 0x0000, EightBit::Chip::Mask16, EightBit::MemoryMapping::AccessLevel::ReadWrite };

View File

@ -26,7 +26,7 @@ public:
virtual void initialise() final; virtual void initialise() final;
protected: protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) final; virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
private: private:
const Configuration& m_configuration; const Configuration& m_configuration;

View File

@ -36,6 +36,6 @@ void Board::initialise() {
}); });
} }
EightBit::MemoryMapping Board::mapping(uint16_t) { EightBit::MemoryMapping Board::mapping(uint16_t) noexcept {
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite }; return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
} }

View File

@ -17,7 +17,7 @@ public:
protected: protected:
void initialise() final; void initialise() final;
EightBit::MemoryMapping mapping(uint16_t address) final; EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
private: private:
EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM

View File

@ -7,6 +7,49 @@
namespace EightBit { namespace EightBit {
class mc6850 final : public ClockedChip { class mc6850 final : public ClockedChip {
public:
// Receive data, (I) Active high
DECLARE_PIN_INPUT(RXDATA)
// Transmit data, (O) Active high
DECLARE_PIN_OUTPUT(TXDATA)
// Request to send, (O) Active low
DECLARE_PIN_OUTPUT(RTS)
// Clear to send, (I) Active low
DECLARE_PIN_INPUT(CTS)
// Data carrier detect, (I) Active low
DECLARE_PIN_INPUT(DCD)
// Transmit clock, (I) Active high
DECLARE_PIN_INPUT(RXCLK)
// Receive clock, (I) Active high
DECLARE_PIN_INPUT(TXCLK)
// Chip select, bit 0, (I) Active high
DECLARE_PIN_INPUT(CS0)
// Chip select, bit 1, (I) Active high
DECLARE_PIN_INPUT(CS1)
// Chip select, bit 2, (I) Active low
DECLARE_PIN_INPUT(CS2)
// Register select, (I) Active high
DECLARE_PIN_INPUT(RS)
// Read/Write, (I) Read high, write low
DECLARE_PIN_INPUT(RW)
// ACIA Enable, (I) Active high
DECLARE_PIN_INPUT(E)
// Interrupt request, (O) Active low
DECLARE_PIN_OUTPUT(IRQ)
public: public:
mc6850(); mc6850();
@ -58,7 +101,7 @@ namespace EightBit {
CR4 = 0b10000, // " CR4 = 0b10000, // "
CR5 = 0b100000, // Transmit control CR5 = 0b100000, // Transmit control
CR6 = 0b1000000, // " CR6 = 0b1000000, // "
CR7 = 0b10000000 // Receive control CR7 = 0b10000000 // Receive control
}; };
// CR0 and CR1 // CR0 and CR1
@ -71,13 +114,13 @@ namespace EightBit {
// CR2, CR3 and CR4 // CR2, CR3 and CR4
enum WordSelect { enum WordSelect {
SevenEvenTwo = 0b000, SevenEvenTwo = 0b000,
SevenOddTwo = 0b001, SevenOddTwo = 0b001,
SevenEvenOne = 0b010, SevenEvenOne = 0b010,
SevenOddOne = 0b011, SevenOddOne = 0b011,
EightTwo = 0b100, EightTwo = 0b100,
EightOne = 0b101, EightOne = 0b101,
EightEvenOne = 0b110, EightEvenOne = 0b110,
EightOddOne = 0b111, EightOddOne = 0b111,
}; };
@ -219,48 +262,6 @@ namespace EightBit {
Signal<EventArgs> Receiving; Signal<EventArgs> Receiving;
Signal<EventArgs> Received; Signal<EventArgs> Received;
// Receive data, (I) Active high
DECLARE_PIN_INPUT(RXDATA)
// Transmit data, (O) Active high
DECLARE_PIN_OUTPUT(TXDATA)
// Request to send, (O) Active low
DECLARE_PIN_OUTPUT(RTS)
// Clear to send, (I) Active low
DECLARE_PIN_INPUT(CTS)
// Data carrier detect, (I) Active low
DECLARE_PIN_INPUT(DCD)
// Transmit clock, (I) Active high
DECLARE_PIN_INPUT(RXCLK)
// Receive clock, (I) Active high
DECLARE_PIN_INPUT(TXCLK)
// Chip select, bit 0, (I) Active high
DECLARE_PIN_INPUT(CS0)
// Chip select, bit 1, (I) Active high
DECLARE_PIN_INPUT(CS1)
// Chip select, bit 2, (I) Active low
DECLARE_PIN_INPUT(CS2)
// Register select, (I) Active high
DECLARE_PIN_INPUT(RS)
// Read/Write, (I) Read high, write low
DECLARE_PIN_INPUT(RW)
// ACIA Enable, (I) Active high
DECLARE_PIN_INPUT(E)
// Interrupt request, (O) Active low
DECLARE_PIN_OUTPUT(IRQ)
private: private:
void step(); void step();

View File

@ -11,7 +11,7 @@ namespace EightBit {
virtual ~Ricoh2A03() = default; virtual ~Ricoh2A03() = default;
protected: protected:
virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow) final; virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow) noexcept final;
virtual uint8_t add(uint8_t operand, uint8_t data, int carry) final; virtual uint8_t add(uint8_t operand, uint8_t data, int carry) noexcept final;
}; };
} }

View File

@ -5,10 +5,10 @@ EightBit::Ricoh2A03::Ricoh2A03(Bus& bus)
: MOS6502(bus) { : MOS6502(bus) {
} }
uint8_t EightBit::Ricoh2A03::sub(uint8_t operand, uint8_t data, int borrow) { uint8_t EightBit::Ricoh2A03::sub(uint8_t operand, uint8_t data, int borrow) noexcept {
return MOS6502::sub_b(operand ,data, borrow); return MOS6502::sub_b(operand ,data, borrow);
} }
uint8_t EightBit::Ricoh2A03::add(uint8_t operand, uint8_t data, int carry) { uint8_t EightBit::Ricoh2A03::add(uint8_t operand, uint8_t data, int carry) noexcept {
return MOS6502::add_b(operand, data, carry); return MOS6502::add_b(operand, data, carry);
} }

View File

@ -65,7 +65,7 @@ void Fuse::TestRunner::lowerPOWER() {
EightBit::Bus::lowerPOWER(); EightBit::Bus::lowerPOWER();
} }
EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) { EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) noexcept {
const bool memory = m_cpu.requestingMemory(); const bool memory = m_cpu.requestingMemory();
if (memory) if (memory)

View File

@ -48,7 +48,7 @@ namespace Fuse {
static void dumpEvent(const TestEvent& event); static void dumpEvent(const TestEvent& event);
protected: protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) final; virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
public: public:
TestRunner(const Test& test, const ExpectedTestResult& expected); TestRunner(const Test& test, const ExpectedTestResult& expected);

View File

@ -14,22 +14,44 @@ namespace EightBit {
class Bus; class Bus;
class Z80 final : public IntelProcessor { class Z80 final : public IntelProcessor {
public:
// ** From the Z80 CPU User Manual
// RFSH.Refresh(output, active Low). RFSH, together with MREQ, indicates that the lower
// seven bits of the systems address bus can be used as a refresh address to the systems
// dynamic memories.
DECLARE_PIN_OUTPUT(RFSH)
DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_OUTPUT(M1)
DECLARE_PIN_OUTPUT(MREQ)
DECLARE_PIN_OUTPUT(IORQ)
DECLARE_PIN_OUTPUT(RD)
DECLARE_PIN_OUTPUT(WR)
private:
DEFINE_PIN_ACTIVATOR_LOW(RFSH)
DEFINE_PIN_ACTIVATOR_LOW(M1)
DEFINE_PIN_ACTIVATOR_LOW(MREQ)
DEFINE_PIN_ACTIVATOR_LOW(IORQ)
DEFINE_PIN_ACTIVATOR_LOW(RD)
DEFINE_PIN_ACTIVATOR_LOW(WR)
public: public:
struct refresh_t { struct refresh_t {
bool high : 1; bool high : 1;
uint8_t variable : 7; uint8_t variable : 7;
refresh_t(const uint8_t value) refresh_t(const uint8_t value) noexcept
: high(!!(value & Bit7)), : high(!!(value & Bit7)),
variable(value & Mask7) variable(value & Mask7)
{ } { }
operator uint8_t() const { constexpr operator uint8_t() const noexcept {
return (high << 7) | variable; return (high << 7) | variable;
} }
auto& operator++() { constexpr auto& operator++() noexcept {
++variable; ++variable;
return *this; return *this;
} }
@ -67,18 +89,18 @@ namespace EightBit {
int execute() final; int execute() final;
int step() final; int step() final;
[[nodiscard]] register16_t& AF() final; [[nodiscard]] register16_t& AF() noexcept final;
[[nodiscard]] register16_t& BC() final; [[nodiscard]] register16_t& BC() noexcept final;
[[nodiscard]] register16_t& DE() final; [[nodiscard]] register16_t& DE() noexcept final;
[[nodiscard]] register16_t& HL() final; [[nodiscard]] register16_t& HL() noexcept final;
[[nodiscard]] auto& IX() { return m_ix; } [[nodiscard]] auto& IX() noexcept { return m_ix; }
[[nodiscard]] auto& IXH() { return IX().high; } [[nodiscard]] auto& IXH() noexcept { return IX().high; }
[[nodiscard]] auto& IXL() { return IX().low; } [[nodiscard]] auto& IXL() noexcept { return IX().low; }
[[nodiscard]] auto& IY() { return m_iy; } [[nodiscard]] auto& IY() noexcept { return m_iy; }
[[nodiscard]] auto& IYH() { return IY().high; } [[nodiscard]] auto& IYH() noexcept { return IY().high; }
[[nodiscard]] auto& IYL() { return IY().low; } [[nodiscard]] auto& IYL() noexcept { return IY().low; }
// ** From the Z80 CPU User Manual // ** From the Z80 CPU User Manual
// Memory Refresh(R) Register.The Z80 CPU contains a memory refresh counter, // Memory Refresh(R) Register.The Z80 CPU contains a memory refresh counter,
@ -91,34 +113,21 @@ namespace EightBit {
// can load the R register for testing purposes, but this register is normally not used by the // can load the R register for testing purposes, but this register is normally not used by the
// programmer. During refresh, the contents of the I Register are placed on the upper eight // programmer. During refresh, the contents of the I Register are placed on the upper eight
// bits of the address bus. // bits of the address bus.
[[nodiscard]] auto& REFRESH() { return m_refresh; } [[nodiscard]] constexpr auto& REFRESH() noexcept { return m_refresh; }
[[nodiscard]] auto& IV() { return iv; } [[nodiscard]] constexpr auto& IV() noexcept { return iv; }
[[nodiscard]] auto& IM() { return m_interruptMode; } [[nodiscard]] constexpr auto& IM() noexcept { return m_interruptMode; }
[[nodiscard]] auto& IFF1() { return m_iff1; } [[nodiscard]] constexpr auto& IFF1() noexcept { return m_iff1; }
[[nodiscard]] auto& IFF2() { return m_iff2; } [[nodiscard]] constexpr auto& IFF2() noexcept { return m_iff2; }
void exx() { m_registerSet ^= 1; } constexpr void exx() noexcept { m_registerSet ^= 1; }
void exxAF() { m_accumulatorFlagsSet ^= 1; } constexpr void exxAF() noexcept { m_accumulatorFlagsSet ^= 1; }
[[nodiscard]] auto requestingIO() const { return lowered(IORQ()); } [[nodiscard]] constexpr auto requestingIO() const noexcept { return lowered(IORQ()); }
[[nodiscard]] auto requestingMemory() const { return lowered(MREQ()); } [[nodiscard]] constexpr auto requestingMemory() const noexcept { return lowered(MREQ()); }
[[nodiscard]] auto requestingRead() const { return lowered(RD()); } [[nodiscard]] constexpr auto requestingRead() const noexcept { return lowered(RD()); }
[[nodiscard]] auto requestingWrite() const { return lowered(WR()); } [[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); }
// ** From the Z80 CPU User Manual
// RFSH.Refresh(output, active Low). RFSH, together with MREQ, indicates that the lower
// seven bits of the systems address bus can be used as a refresh address to the systems
// dynamic memories.
DECLARE_PIN_OUTPUT(RFSH)
DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_OUTPUT(M1)
DECLARE_PIN_OUTPUT(MREQ)
DECLARE_PIN_OUTPUT(IORQ)
DECLARE_PIN_OUTPUT(RD)
DECLARE_PIN_OUTPUT(WR)
protected: protected:
void handleRESET() final; void handleRESET() final;
@ -136,14 +145,6 @@ namespace EightBit {
int jrConditional(int condition) final; int jrConditional(int condition) final;
private: private:
DEFINE_PIN_ACTIVATOR_LOW(RFSH)
DEFINE_PIN_ACTIVATOR_LOW(M1)
DEFINE_PIN_ACTIVATOR_LOW(MREQ)
DEFINE_PIN_ACTIVATOR_LOW(IORQ)
DEFINE_PIN_ACTIVATOR_LOW(RD)
DEFINE_PIN_ACTIVATOR_LOW(WR)
enum { BC_IDX, DE_IDX, HL_IDX }; enum { BC_IDX, DE_IDX, HL_IDX };
std::array<std::array<register16_t, 3>, 2> m_registers; std::array<std::array<register16_t, 3>, 2> m_registers;
@ -171,10 +172,10 @@ namespace EightBit {
void handleNMI(); void handleNMI();
void resetPrefixes(); void resetPrefixes() noexcept;
[[nodiscard]] auto displaced() const { return m_prefixDD || m_prefixFD; } [[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; }
[[nodiscard]] uint16_t displacedAddress(); [[nodiscard]] uint16_t displacedAddress() noexcept;
void fetchDisplacement(); void fetchDisplacement();
[[nodiscard]] uint8_t fetchOpCode(); [[nodiscard]] uint8_t fetchOpCode();
@ -187,34 +188,34 @@ namespace EightBit {
typedef std::function<uint8_t(void)> reader_t; typedef std::function<uint8_t(void)> reader_t;
void readInternalRegister(reader_t reader); void readInternalRegister(reader_t reader);
[[nodiscard]] register16_t& HL2(); [[nodiscard]] register16_t& HL2() noexcept;
[[nodiscard]] register16_t& RP(int rp); [[nodiscard]] register16_t& RP(int rp) noexcept;
[[nodiscard]] register16_t& RP2(int rp); [[nodiscard]] register16_t& RP2(int rp) noexcept;
[[nodiscard]] uint8_t R(int r); [[nodiscard]] uint8_t R(int r);
void R(int r, uint8_t value); void R(int r, uint8_t value);
void R2(int r, uint8_t value); void R2(int r, uint8_t value);
[[nodiscard]] static uint8_t adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation); [[nodiscard]] static uint8_t adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept;
[[nodiscard]] static uint8_t adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation); [[nodiscard]] static uint8_t adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept;
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation); [[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept;
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative); [[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept;
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation); [[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept;
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative); [[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept;
[[nodiscard]] static bool convertCondition(uint8_t f, int flag); [[nodiscard]] static bool convertCondition(uint8_t f, int flag) noexcept;
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0); static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
void executeCB(int x, int y, int z); void executeCB(int x, int y, int z);
void executeED(int x, int y, int z, int p, int q); void executeED(int x, int y, int z, int p, int q);
void executeOther(int x, int y, int z, int p, int q); void executeOther(int x, int y, int z, int p, int q);
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand) noexcept;
void di(); void di() noexcept;
void ei(); void ei() noexcept;
void retn(); void retn();
void reti(); void reti();
@ -228,33 +229,33 @@ namespace EightBit {
[[nodiscard]] register16_t adc(uint8_t& f, register16_t operand, register16_t value); [[nodiscard]] register16_t adc(uint8_t& f, register16_t operand, register16_t value);
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value, int carry = 0); [[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value, int carry = 0);
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0); [[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0); [[nodiscard]] static uint8_t sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value); [[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
static void compare(uint8_t& f, uint8_t operand, uint8_t value); static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sll(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t sll(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
static void bit(uint8_t& f, int n, uint8_t operand); static void bit(uint8_t& f, int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t res(int n, uint8_t operand); [[nodiscard]] static uint8_t res(int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t set(int n, uint8_t operand); [[nodiscard]] static uint8_t set(int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand) noexcept;
static void scf(uint8_t& f, uint8_t operand); static void scf(uint8_t& f, uint8_t operand) noexcept;
static void ccf(uint8_t& f, uint8_t operand); static void ccf(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand); [[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand) noexcept;
void xhtl(register16_t& exchange); void xhtl(register16_t& exchange);
@ -290,7 +291,7 @@ namespace EightBit {
void outd(); void outd();
[[nodiscard]] bool otdr(); [[nodiscard]] bool otdr();
[[nodiscard]] uint8_t neg(uint8_t& f, uint8_t operand); [[nodiscard]] uint8_t neg(uint8_t& f, uint8_t operand) noexcept;
void rrd(uint8_t& f, register16_t address, uint8_t& update); void rrd(uint8_t& f, register16_t address, uint8_t& update);
void rld(uint8_t& f, register16_t address, uint8_t& update); void rld(uint8_t& f, register16_t address, uint8_t& update);

View File

@ -127,15 +127,11 @@ std::string EightBit::Disassembler::R(int r) const {
return "IYL"; return "IYL";
return "L"; return "L";
case 6: case 6:
if (m_prefixDD || m_prefixFD) { if (m_prefixDD)
if (m_prefixDD) return "IX+%4%";
return "IX+%4%"; if (m_prefixFD)
if (m_prefixFD) return "IY+%4%";
return "IY+%4%"; return "(HL)";
}
else {
return "(HL)";
}
case 7: case 7:
return "A"; return "A";
} }

View File

@ -41,19 +41,19 @@ DEFINE_PIN_LEVEL_CHANGERS(IORQ, Z80);
DEFINE_PIN_LEVEL_CHANGERS(RD, Z80); DEFINE_PIN_LEVEL_CHANGERS(RD, Z80);
DEFINE_PIN_LEVEL_CHANGERS(WR, Z80); DEFINE_PIN_LEVEL_CHANGERS(WR, Z80);
EightBit::register16_t& EightBit::Z80::AF() { EightBit::register16_t& EightBit::Z80::AF() noexcept {
return m_accumulatorFlags[m_accumulatorFlagsSet]; return m_accumulatorFlags[m_accumulatorFlagsSet];
} }
EightBit::register16_t& EightBit::Z80::BC() { EightBit::register16_t& EightBit::Z80::BC() noexcept {
return m_registers[m_registerSet][BC_IDX]; return m_registers[m_registerSet][BC_IDX];
} }
EightBit::register16_t& EightBit::Z80::DE() { EightBit::register16_t& EightBit::Z80::DE() noexcept {
return m_registers[m_registerSet][DE_IDX]; return m_registers[m_registerSet][DE_IDX];
} }
EightBit::register16_t& EightBit::Z80::HL() { EightBit::register16_t& EightBit::Z80::HL() noexcept {
return m_registers[m_registerSet][HL_IDX]; return m_registers[m_registerSet][HL_IDX];
} }
@ -160,15 +160,15 @@ void EightBit::Z80::handleINT() {
} }
} }
void EightBit::Z80::di() { void EightBit::Z80::di() noexcept {
IFF1() = IFF2() = false; IFF1() = IFF2() = false;
} }
void EightBit::Z80::ei() { void EightBit::Z80::ei() noexcept {
IFF1() = IFF2() = true; IFF1() = IFF2() = true;
} }
uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF); f = clearBit(f, NF);
const uint8_t result = operand + 1; const uint8_t result = operand + 1;
f = adjustSZXY<Z80>(f, result); f = adjustSZXY<Z80>(f, result);
@ -177,7 +177,7 @@ uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) noexcept {
f = setBit(f, NF); f = setBit(f, NF);
f = clearBit(f, HC, lowNibble(operand)); f = clearBit(f, HC, lowNibble(operand));
const uint8_t result = operand - 1; const uint8_t result = operand - 1;
@ -186,33 +186,33 @@ uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::adjustHalfCarryAdd(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) { uint8_t EightBit::Z80::adjustHalfCarryAdd(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation)); return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
} }
uint8_t EightBit::Z80::adjustHalfCarrySub(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) { uint8_t EightBit::Z80::adjustHalfCarrySub(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation)); return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
} }
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) { uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept {
return adjustOverflowAdd(f, before & SF, value & SF, calculation & SF); return adjustOverflowAdd(f, before & SF, value & SF, calculation & SF);
} }
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) { uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept {
const auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative); const auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
return setBit(f, VF, overflow); return setBit(f, VF, overflow);
} }
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) { uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept {
return adjustOverflowSub(f, before & SF, value & SF, calculation & SF); return adjustOverflowSub(f, before & SF, value & SF, calculation & SF);
} }
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) { uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept {
const auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative); const auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
return setBit(f, VF, overflow); return setBit(f, VF, overflow);
} }
bool EightBit::Z80::convertCondition(const uint8_t f, int flag) { bool EightBit::Z80::convertCondition(const uint8_t f, int flag) noexcept {
switch (flag) { switch (flag) {
case 0: case 0:
return !(f & ZF); return !(f & ZF);
@ -328,7 +328,7 @@ EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand
return result; return result;
} }
uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) { uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
const register16_t addition = operand + value + carry; const register16_t addition = operand + value + carry;
const auto result = addition.low; const auto result = addition.low;
@ -343,11 +343,11 @@ uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t valu
return result; return result;
} }
uint8_t EightBit::Z80::adc(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::Z80::adc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
return add(f, operand, value, f & CF); return add(f, operand, value, f & CF);
} }
uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) { uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
const register16_t subtraction = operand - value - carry; const register16_t subtraction = operand - value - carry;
const auto result = subtraction.low; const auto result = subtraction.low;
@ -362,17 +362,17 @@ uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t
return result; return result;
} }
uint8_t EightBit::Z80::sub(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) { uint8_t EightBit::Z80::sub(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
const auto subtraction = subtract(f, operand, value, carry); const auto subtraction = subtract(f, operand, value, carry);
f = adjustXY<Z80>(f, subtraction); f = adjustXY<Z80>(f, subtraction);
return subtraction; return subtraction;
} }
uint8_t EightBit::Z80::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::Z80::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
return sub(f, operand, value, f & CF); return sub(f, operand, value, f & CF);
} }
uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
f = setBit(f, HC); f = setBit(f, HC);
f = clearBit(f, CF | NF); f = clearBit(f, CF | NF);
const uint8_t result = operand & value; const uint8_t result = operand & value;
@ -380,26 +380,26 @@ uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t val
return result; return result;
} }
uint8_t EightBit::Z80::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::Z80::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
f = clearBit(f, HC | CF | NF); f = clearBit(f, HC | CF | NF);
const uint8_t result = operand ^ value; const uint8_t result = operand ^ value;
f = adjustSZPXY<Z80>(f, result); f = adjustSZPXY<Z80>(f, result);
return result; return result;
} }
uint8_t EightBit::Z80::orr(uint8_t& f, const uint8_t operand, const uint8_t value) { uint8_t EightBit::Z80::orr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
f = clearBit(f, HC | CF | NF); f = clearBit(f, HC | CF | NF);
const uint8_t result = operand | value; const uint8_t result = operand | value;
f = adjustSZPXY<Z80>(f, result); f = adjustSZPXY<Z80>(f, result);
return result; return result;
} }
void EightBit::Z80::compare(uint8_t& f, uint8_t operand, const uint8_t value) { void EightBit::Z80::compare(uint8_t& f, uint8_t operand, const uint8_t value) noexcept {
subtract(f, operand, value); subtract(f, operand, value);
f = adjustXY<Z80>(f, value); f = adjustXY<Z80>(f, value);
} }
uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
const auto carry = operand & Bit7; const auto carry = operand & Bit7;
f = setBit(f, CF, carry); f = setBit(f, CF, carry);
@ -408,7 +408,7 @@ uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
const auto carry = operand & Bit0; const auto carry = operand & Bit0;
f = setBit(f, CF, carry); f = setBit(f, CF, carry);
@ -417,7 +417,7 @@ uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
const auto carry = f & CF; const auto carry = f & CF;
f = setBit(f, CF, operand & Bit7); f = setBit(f, CF, operand & Bit7);
@ -426,7 +426,7 @@ uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
const auto carry = f & CF; const auto carry = f & CF;
f = setBit(f, CF, operand & Bit0); f = setBit(f, CF, operand & Bit0);
@ -437,7 +437,7 @@ uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) {
// //
uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
f = setBit(f, CF, operand & Bit7); f = setBit(f, CF, operand & Bit7);
const uint8_t result = operand << 1; const uint8_t result = operand << 1;
@ -445,7 +445,7 @@ uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
f = setBit(f, CF, operand & Bit0); f = setBit(f, CF, operand & Bit0);
const uint8_t result = (operand >> 1) | (operand & Bit7); const uint8_t result = (operand >> 1) | (operand & Bit7);
@ -453,7 +453,7 @@ uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
f = setBit(f, CF, operand & Bit7); f = setBit(f, CF, operand & Bit7);
const uint8_t result = (operand << 1) | Bit0; const uint8_t result = (operand << 1) | Bit0;
@ -461,7 +461,7 @@ uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF | HC); f = clearBit(f, NF | HC);
f = setBit(f, CF, operand & Bit0); f = setBit(f, CF, operand & Bit0);
const uint8_t result = (operand >> 1) & ~Bit7; const uint8_t result = (operand >> 1) & ~Bit7;
@ -470,7 +470,7 @@ uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) {
return result; return result;
} }
void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) { void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) noexcept {
f = setBit(f, HC); f = setBit(f, HC);
f = clearBit(f, NF); f = clearBit(f, NF);
const auto discarded = operand & Chip::bit(n); const auto discarded = operand & Chip::bit(n);
@ -478,15 +478,15 @@ void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) {
f = clearBit(f, PF, discarded); f = clearBit(f, PF, discarded);
} }
uint8_t EightBit::Z80::res(const int n, const uint8_t operand) { uint8_t EightBit::Z80::res(const int n, const uint8_t operand) noexcept {
return clearBit(operand, Chip::bit(n)); return clearBit(operand, Chip::bit(n));
} }
uint8_t EightBit::Z80::set(const int n, const uint8_t operand) { uint8_t EightBit::Z80::set(const int n, const uint8_t operand) noexcept {
return setBit(operand, Chip::bit(n)); return setBit(operand, Chip::bit(n));
} }
uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) { uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) noexcept {
f = setBit(f, PF, operand == Bit7); f = setBit(f, PF, operand == Bit7);
f = setBit(f, CF, operand); f = setBit(f, CF, operand);
@ -502,7 +502,7 @@ uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) {
return result; return result;
} }
uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) { uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) noexcept {
const auto lowAdjust = (f & HC) || (lowNibble(operand) > 9); const auto lowAdjust = (f & HC) || (lowNibble(operand) > 9);
const auto highAdjust = (f & CF) || (operand > 0x99); const auto highAdjust = (f & CF) || (operand > 0x99);
@ -527,20 +527,20 @@ uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) {
return updated; return updated;
} }
uint8_t EightBit::Z80::cpl(uint8_t& f, const uint8_t operand) { uint8_t EightBit::Z80::cpl(uint8_t& f, const uint8_t operand) noexcept {
f = setBit(f, HC | NF); f = setBit(f, HC | NF);
const uint8_t result = ~operand; const uint8_t result = ~operand;
f = adjustXY<Z80>(f, result); f = adjustXY<Z80>(f, result);
return result; return result;
} }
void EightBit::Z80::scf(uint8_t& f, const uint8_t operand) { void EightBit::Z80::scf(uint8_t& f, const uint8_t operand) noexcept {
f = setBit(f, CF); f = setBit(f, CF);
f = clearBit(f, HC | NF); f = clearBit(f, HC | NF);
f = adjustXY<Z80>(f, operand); f = adjustXY<Z80>(f, operand);
} }
void EightBit::Z80::ccf(uint8_t& f, const uint8_t operand) { void EightBit::Z80::ccf(uint8_t& f, const uint8_t operand) noexcept {
f = clearBit(f, NF); f = clearBit(f, NF);
const auto carry = f & CF; const auto carry = f & CF;
f = setBit(f, HC, carry); f = setBit(f, HC, carry);
@ -766,13 +766,13 @@ uint8_t EightBit::Z80::portRead() {
// //
void EightBit::Z80::resetPrefixes() { void EightBit::Z80::resetPrefixes() noexcept {
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false; m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
} }
// //
uint16_t EightBit::Z80::displacedAddress() { uint16_t EightBit::Z80::displacedAddress() noexcept {
return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement; return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
} }
@ -851,7 +851,7 @@ void EightBit::Z80::readInternalRegister(reader_t reader) {
tick(); tick();
} }
EightBit::register16_t& EightBit::Z80::HL2() { EightBit::register16_t& EightBit::Z80::HL2() noexcept {
if (UNLIKELY(m_prefixDD)) if (UNLIKELY(m_prefixDD))
return IX(); return IX();
if (UNLIKELY(m_prefixFD)) if (UNLIKELY(m_prefixFD))
@ -859,7 +859,7 @@ EightBit::register16_t& EightBit::Z80::HL2() {
return HL(); return HL();
} }
EightBit::register16_t& EightBit::Z80::RP(const int rp) { EightBit::register16_t& EightBit::Z80::RP(const int rp) noexcept {
switch (rp) { switch (rp) {
case 0b00: case 0b00:
return BC(); return BC();
@ -874,7 +874,7 @@ EightBit::register16_t& EightBit::Z80::RP(const int rp) {
} }
} }
EightBit::register16_t& EightBit::Z80::RP2(const int rp) { EightBit::register16_t& EightBit::Z80::RP2(const int rp) noexcept {
switch (rp) { switch (rp) {
case 0b00: case 0b00:
return BC(); return BC();

View File

@ -8,10 +8,10 @@ namespace EightBit {
class BigEndianProcessor : public Processor { class BigEndianProcessor : public Processor {
public: public:
virtual ~BigEndianProcessor() = default; virtual ~BigEndianProcessor() noexcept {};
[[nodiscard]] register16_t peekWord(register16_t address) final; [[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
void pokeWord(register16_t address, register16_t value) final; void pokeWord(register16_t address, register16_t value) noexcept final;
protected: protected:
BigEndianProcessor(Bus& memory); BigEndianProcessor(Bus& memory);

View File

@ -12,7 +12,7 @@
namespace EightBit { namespace EightBit {
class Bus : public Mapper { class Bus : public Mapper {
public: public:
virtual ~Bus() = default; virtual ~Bus() {};
Signal<EventArgs> WritingByte; Signal<EventArgs> WritingByte;
Signal<EventArgs> WrittenByte; Signal<EventArgs> WrittenByte;
@ -26,12 +26,12 @@ namespace EightBit {
[[nodiscard]] auto DATA() const noexcept { return m_data; } [[nodiscard]] auto DATA() const noexcept { return m_data; }
[[nodiscard]] auto& DATA() noexcept { return m_data; } [[nodiscard]] auto& DATA() noexcept { return m_data; }
[[nodiscard]] auto peek() { return reference(); } [[nodiscard]] auto peek() noexcept { return reference(); }
[[nodiscard]] virtual uint8_t peek(const uint16_t address) { return reference(address); } [[nodiscard]] virtual uint8_t peek(const uint16_t address) noexcept { return reference(address); }
[[nodiscard]] auto peek(const register16_t address) { return peek(address.word); } [[nodiscard]] auto peek(const register16_t address) noexcept { return peek(address.word); }
void poke(const uint8_t value) { reference() = value; } void poke(const uint8_t value) noexcept { reference() = value; }
virtual void poke(const uint16_t address, const uint8_t value) { reference(address) = value; } virtual void poke(const uint16_t address, const uint8_t value) noexcept { reference(address) = value; }
void poke(const register16_t address, const uint8_t value) { poke(address.word, value); } void poke(const register16_t address, const uint8_t value) noexcept { poke(address.word, value); }
[[nodiscard]] uint8_t read(); [[nodiscard]] uint8_t read();
template<class T> [[nodiscard]] auto read(const T address) { template<class T> [[nodiscard]] auto read(const T address) {
@ -52,9 +52,9 @@ namespace EightBit {
virtual void initialise() = 0; virtual void initialise() = 0;
protected: protected:
[[nodiscard]] uint8_t& reference(uint16_t address); [[nodiscard]] uint8_t& reference(uint16_t address) noexcept;
[[nodiscard]] auto& reference(const register16_t address) { return reference(address.word); } [[nodiscard]] auto& reference(const register16_t address) noexcept { return reference(address.word); }
[[nodiscard]] uint8_t& reference() { return reference(ADDRESS()); } [[nodiscard]] uint8_t& reference() noexcept { return reference(ADDRESS()); }
void loadHexFile(std::string path); void loadHexFile(std::string path);

View File

@ -57,18 +57,18 @@ namespace EightBit {
[[nodiscard]] static constexpr uint8_t clearBit(uint8_t input, const int which, const uint32_t condition) noexcept { return clearBit(input, which, !!condition); } [[nodiscard]] static constexpr uint8_t clearBit(uint8_t input, const int which, const uint32_t condition) noexcept { return clearBit(input, which, !!condition); }
[[nodiscard]] static constexpr uint8_t clearBit(uint8_t input, const int which, const bool condition) noexcept { return setBit(input, which, !condition); } [[nodiscard]] static constexpr uint8_t clearBit(uint8_t input, const int which, const bool condition) noexcept { return setBit(input, which, !condition); }
[[nodiscard]] static constexpr auto highNibble(const int value) { return value >> 4; } [[nodiscard]] static constexpr auto highNibble(const int value) noexcept { return value >> 4; }
[[nodiscard]] static constexpr auto lowNibble(const int value) { return value & Mask4; } [[nodiscard]] static constexpr auto lowNibble(const int value) noexcept { return value & Mask4; }
[[nodiscard]] static constexpr auto higherNibble(const int value) { return value & 0xf0; } [[nodiscard]] static constexpr auto higherNibble(const int value) noexcept { return value & 0xf0; }
[[nodiscard]] static constexpr auto lowerNibble(const int value) { return lowNibble(value); } [[nodiscard]] static constexpr auto lowerNibble(const int value) noexcept { return lowNibble(value); }
[[nodiscard]] static constexpr auto promoteNibble(const int value) { return value << 4; } [[nodiscard]] static constexpr auto promoteNibble(const int value) noexcept { return value << 4; }
[[nodiscard]] static constexpr auto demoteNibble(const int value) { return highNibble(value); } [[nodiscard]] static constexpr auto demoteNibble(const int value) noexcept { return highNibble(value); }
~Chip() = default; virtual ~Chip() {}
protected: protected:
Chip() = default; Chip() noexcept = default;
}; };
} }

View File

@ -7,16 +7,18 @@
namespace EightBit { namespace EightBit {
class ClockedChip : public Chip { class ClockedChip : public Chip {
public: public:
~ClockedChip() = default; virtual ~ClockedChip() noexcept {};
Signal<EventArgs> Ticked; Signal<EventArgs> Ticked;
[[nodiscard]] auto cycles() const noexcept { return m_cycles; } [[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; }
void tick(int extra); void tick(int extra);
void tick(); void tick();
protected: protected:
ClockedChip() noexcept = default;
void resetCycles() noexcept; void resetCycles() noexcept;
private: private:

View File

@ -48,11 +48,11 @@
template <class T> class _Activate ## name final { \ template <class T> class _Activate ## name final { \
T& m_parent; \ T& m_parent; \
public: \ public: \
_Activate ## name(T& parent) \ _Activate ## name(T& parent) noexcept \
: m_parent(parent) { \ : m_parent(parent) { \
m_parent. on ## name(); \ m_parent. on ## name(); \
} \ } \
~_Activate ## name() { \ ~_Activate ## name() noexcept { \
m_parent. off ## name(); \ m_parent. off ## name(); \
} \ } \
}; };
@ -66,10 +66,10 @@
#define DECLARE_PIN(name, visibility) \ #define DECLARE_PIN(name, visibility) \
public: \ public: \
DECLARE_PIN_SIGNALS(name) \ DECLARE_PIN_SIGNALS(name) \
[[nodiscard]] PinLevel& name () noexcept { \ [[nodiscard]] constexpr auto& name () noexcept { \
return m_## name ## _Line; \ return m_## name ## _Line; \
} \ } \
[[nodiscard]] const PinLevel& name () const noexcept { \ [[nodiscard]] constexpr const auto& name () const noexcept { \
return m_## name ## _Line; \ return m_## name ## _Line; \
} \ } \
visibility : \ visibility : \
@ -92,22 +92,23 @@ namespace EightBit {
Low, High Low, High
}; };
[[nodiscard]] static constexpr auto raised(const PinLevel line) { return line == PinLevel::High; }
static void raise(PinLevel& line) noexcept { line = PinLevel::High; }
[[nodiscard]] static constexpr auto lowered(const PinLevel line) { return line == PinLevel::Low; }
static void lower(PinLevel& line) noexcept { line = PinLevel::Low; }
static void match(PinLevel& line, int condition) noexcept { match(line, condition != 0); }
static void match(PinLevel& line, bool condition) noexcept { condition ? raise(line) : lower(line); }
static void match(PinLevel& out, PinLevel in) noexcept { out = in; }
virtual ~Device() = default;
[[nodiscard]] bool powered() const noexcept { return raised(POWER()); }
DECLARE_PIN_INPUT(POWER) DECLARE_PIN_INPUT(POWER)
public:
[[nodiscard]] static constexpr auto raised(const PinLevel line) noexcept { return line == PinLevel::High; }
static constexpr void raise(PinLevel& line) noexcept { line = PinLevel::High; }
[[nodiscard]] static constexpr auto lowered(const PinLevel line) noexcept { return line == PinLevel::Low; }
static constexpr void lower(PinLevel& line) noexcept { line = PinLevel::Low; }
static constexpr void match(PinLevel& line, int condition) noexcept { match(line, condition != 0); }
static constexpr void match(PinLevel& line, bool condition) noexcept { condition ? raise(line) : lower(line); }
static constexpr void match(PinLevel& out, PinLevel in) noexcept { out = in; }
virtual ~Device() noexcept {};
[[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); }
protected: protected:
Device() noexcept = default; Device() noexcept {};
}; };
} }

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <cassert>
#ifdef _MSC_VER #ifdef _MSC_VER
# include <intrin.h> # include <intrin.h>
#endif #endif
@ -9,7 +11,6 @@
#endif #endif
#if !(defined(_MSC_VER) || defined(__GNUG__)) #if !(defined(_MSC_VER) || defined(__GNUG__))
# include <cassert>
# include <bitset> # include <bitset>
#endif #endif
@ -70,18 +71,18 @@ inline int EightBit::findFirstSet(const unsigned long value) noexcept {
#ifdef _MSC_VER #ifdef _MSC_VER
# define ASSUME(x) __assume(x); # define ASSUME(x) __assume(x);
# define LIKELY(x) (x) # define LIKELY(x) (x)
# define UNLIKELY(x) (x) # define UNLIKELY(x) (x)
# define UNREACHABLE { ASSUME(0); throw std::exception("unreachable"); } # define UNREACHABLE { ASSUME(0); assert(false && "unreachable"); }
#elif defined(__GNUG__) #elif defined(__GNUG__)
# define ASSUME(x) { if (!x) __builtin_unreachable(); } # define ASSUME(x) { if (!x) __builtin_unreachable(); }
# define LIKELY(x) __builtin_expect(!!(x), 1) # define LIKELY(x) __builtin_expect(!!(x), 1)
# define UNLIKELY(x) __builtin_expect(!!(x), 0) # define UNLIKELY(x) __builtin_expect(!!(x), 0)
# define UNREACHABLE __builtin_unreachable(); # define UNREACHABLE __builtin_unreachable();
@ -90,7 +91,7 @@ inline int EightBit::findFirstSet(const unsigned long value) noexcept {
# define ASSUME(x) assert(x); # define ASSUME(x) assert(x);
# define LIKELY(x) (x) # define LIKELY(x) (x)
# define UNLIKELY(x) (x) # define UNLIKELY(x) (x)
# define UNREACHABLE ASSUME(0) # define UNREACHABLE ASSUME(0)

View File

@ -6,6 +6,6 @@ namespace EightBit {
static EventArgs m_empty; static EventArgs m_empty;
public: public:
[[nodiscard]] static auto& empty() noexcept { return m_empty; } [[nodiscard]] static constexpr auto& empty() noexcept { return m_empty; }
}; };
} }

View File

@ -11,39 +11,40 @@ namespace EightBit {
enum class AccessType { Unknown, Reading, Writing }; enum class AccessType { Unknown, Reading, Writing };
[[nodiscard]] size_t size() const noexcept override; [[nodiscard]] size_t size() const noexcept override;
[[nodiscard]] uint8_t peek(uint16_t address) const override; [[nodiscard]] uint8_t peek(uint16_t address) const noexcept override;
[[nodiscard]] uint8_t& reference(uint16_t address) override; [[nodiscard]] uint8_t& reference(uint16_t address) noexcept override;
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) override; int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) override; int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) override; int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) override;
[[nodiscard]] const AccessType& accessType() const noexcept { return m_access; } [[nodiscard]] constexpr const auto& accessType() const noexcept { return m_access; }
[[nodiscard]] AccessType& accessType() noexcept { return m_access; } [[nodiscard]] constexpr auto& accessType() noexcept { return m_access; }
[[nodiscard]] auto readPort(uint8_t port, AccessType access) { [[nodiscard]] auto readPort(uint8_t port, AccessType access) noexcept {
accessType() = access; accessType() = access;
return reference(port); return reference(port);
} }
[[nodiscard]] auto readInputPort(uint8_t port) { return readPort(port, AccessType::Reading); } [[nodiscard]] auto readInputPort(uint8_t port) noexcept { return readPort(port, AccessType::Reading); }
[[nodiscard]] auto readOutputPort(uint8_t port) { return readPort(port, AccessType::Writing); } [[nodiscard]] auto readOutputPort(uint8_t port) noexcept { return readPort(port, AccessType::Writing); }
void writePort(uint8_t port, uint8_t value, AccessType access) { void writePort(uint8_t port, uint8_t value, AccessType access) noexcept {
accessType() = access; accessType() = access;
reference(port) = value; reference(port) = value;
} }
void writeInputPort(uint8_t port, uint8_t value) { writePort(port, value, AccessType::Reading); } void writeInputPort(uint8_t port, uint8_t value) noexcept { writePort(port, value, AccessType::Reading); }
void writeOutputPort(uint8_t port, uint8_t value) { writePort(port, value, AccessType::Writing); } void writeOutputPort(uint8_t port, uint8_t value) noexcept { writePort(port, value, AccessType::Writing); }
protected: protected:
void poke(uint16_t address, uint8_t value) override; void poke(uint16_t address, uint8_t value) noexcept override;
private: private:
Ram m_input = 0x100; Ram m_input = 0x100;
Ram m_output = 0x100; Ram m_output = 0x100;
uint8_t m_delivered = 0xff;
AccessType m_access = AccessType::Unknown; AccessType m_access = AccessType::Unknown;
}; };

View File

@ -23,9 +23,9 @@ namespace EightBit {
int p = 0; int p = 0;
int q = 0; int q = 0;
opcode_decoded_t() noexcept {} constexpr opcode_decoded_t() noexcept {}
opcode_decoded_t(const uint8_t opcode) noexcept { constexpr opcode_decoded_t(const uint8_t opcode) noexcept {
x = (opcode & 0b11000000) >> 6; // 0 - 3 x = (opcode & 0b11000000) >> 6; // 0 - 3
y = (opcode & 0b00111000) >> 3; // 0 - 7 y = (opcode & 0b00111000) >> 3; // 0 - 7
z = (opcode & 0b00000111); // 0 - 7 z = (opcode & 0b00000111); // 0 - 7
@ -34,77 +34,77 @@ namespace EightBit {
} }
}; };
~IntelProcessor() = default; virtual ~IntelProcessor() {};
[[nodiscard]] const auto& getDecodedOpcode(const size_t i) const noexcept { [[nodiscard]] constexpr const auto& getDecodedOpcode(const size_t i) const noexcept {
return m_decodedOpcodes[i]; return m_decodedOpcodes[i];
} }
[[nodiscard]] auto& MEMPTR() noexcept { return m_memptr; } [[nodiscard]] constexpr auto& MEMPTR() noexcept { return m_memptr; }
[[nodiscard]] auto& SP() noexcept { return m_sp; } [[nodiscard]] constexpr auto& SP() noexcept { return m_sp; }
[[nodiscard]] virtual register16_t& AF() = 0; [[nodiscard]] virtual register16_t& AF() noexcept = 0;
[[nodiscard]] auto& A() { return AF().high; } [[nodiscard]] auto& A() noexcept { return AF().high; }
[[nodiscard]] auto& F() { return AF().low; } [[nodiscard]] auto& F() noexcept { return AF().low; }
[[nodiscard]] virtual register16_t& BC() = 0; [[nodiscard]] virtual register16_t& BC() noexcept = 0;
[[nodiscard]] auto& B() { return BC().high; } [[nodiscard]] auto& B() noexcept { return BC().high; }
[[nodiscard]] auto& C() { return BC().low; } [[nodiscard]] auto& C() noexcept { return BC().low; }
[[nodiscard]] virtual register16_t& DE() = 0; [[nodiscard]] virtual register16_t& DE() noexcept = 0;
[[nodiscard]] auto& D() { return DE().high; } [[nodiscard]] auto& D() noexcept { return DE().high; }
[[nodiscard]] auto& E() { return DE().low; } [[nodiscard]] auto& E() noexcept { return DE().low; }
[[nodiscard]] virtual register16_t& HL() = 0; [[nodiscard]] virtual register16_t& HL() noexcept = 0;
[[nodiscard]] auto& H() { return HL().high; } [[nodiscard]] auto& H() noexcept { return HL().high; }
[[nodiscard]] auto& L() { return HL().low; } [[nodiscard]] auto& L() noexcept { return HL().low; }
DECLARE_PIN_OUTPUT(HALT) DECLARE_PIN_OUTPUT(HALT)
protected: protected:
IntelProcessor(Bus& bus); IntelProcessor(Bus& bus);
template<class T> [[nodiscard]] static uint8_t adjustSign(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustSign(uint8_t f, const uint8_t value) noexcept {
return setBit(f, T::SF, value & T::SF); return setBit(f, T::SF, value & T::SF);
} }
template<class T> [[nodiscard]] static uint8_t adjustZero(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustZero(uint8_t f, const uint8_t value) noexcept {
return clearBit(f, T::ZF, value); return clearBit(f, T::ZF, value);
} }
template<class T> [[nodiscard]] static uint8_t adjustParity(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustParity(uint8_t f, const uint8_t value) noexcept {
return clearBit(f, T::PF, PARITY(value)); return clearBit(f, T::PF, PARITY(value));
} }
template<class T> [[nodiscard]] static uint8_t adjustSZ(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustSZ(uint8_t f, const uint8_t value) noexcept {
const auto intermediate = adjustSign<T>(f, value); const auto intermediate = adjustSign<T>(f, value);
return adjustZero<T>(intermediate, value); return adjustZero<T>(intermediate, value);
} }
template<class T> [[nodiscard]] static uint8_t adjustSZP(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustSZP(uint8_t f, const uint8_t value) noexcept {
const auto intermediate = adjustSZ<T>(f, value); const auto intermediate = adjustSZ<T>(f, value);
return adjustParity<T>(intermediate, value); return adjustParity<T>(intermediate, value);
} }
template<class T> [[nodiscard]] static uint8_t adjustXY(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustXY(uint8_t f, const uint8_t value) noexcept {
const auto intermediate = setBit(f, T::XF, value & T::XF); const auto intermediate = setBit(f, T::XF, value & T::XF);
return setBit(intermediate, T::YF, value & T::YF); return setBit(intermediate, T::YF, value & T::YF);
} }
template<class T> [[nodiscard]] static uint8_t adjustSZPXY(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustSZPXY(uint8_t f, const uint8_t value) noexcept {
const auto intermediate = adjustSZP<T>(f, value); const auto intermediate = adjustSZP<T>(f, value);
return adjustXY<T>(intermediate, value); return adjustXY<T>(intermediate, value);
} }
template<class T> [[nodiscard]] static uint8_t adjustSZXY(uint8_t f, const uint8_t value) { template<class T> [[nodiscard]] static constexpr uint8_t adjustSZXY(uint8_t f, const uint8_t value) noexcept {
const auto intermediate = adjustSZ<T>(f, value); const auto intermediate = adjustSZ<T>(f, value);
return adjustXY<T>(intermediate, value); return adjustXY<T>(intermediate, value);
} }
// //
[[nodiscard]] static constexpr auto buildHalfCarryIndex(const uint8_t before, const uint8_t value, const int calculation) { [[nodiscard]] static constexpr auto buildHalfCarryIndex(const uint8_t before, const uint8_t value, const int calculation) noexcept {
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3); return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
} }
@ -114,7 +114,7 @@ namespace EightBit {
return halfCarryTableAdd[index & Mask3]; return halfCarryTableAdd[index & Mask3];
} }
[[nodiscard]] static auto calculateHalfCarrySub(const uint8_t before, const uint8_t value, const int calculation) noexcept { [[nodiscard]] static constexpr auto calculateHalfCarrySub(const uint8_t before, const uint8_t value, const int calculation) noexcept {
std::array<int, 8> halfCarryTableSub = { { 0, 1, 1, 1, 0, 0, 0, 1 } }; std::array<int, 8> halfCarryTableSub = { { 0, 1, 1, 1, 0, 0, 0, 1 } };
const auto index = buildHalfCarryIndex(before, value, calculation); const auto index = buildHalfCarryIndex(before, value, calculation);
return halfCarryTableSub[index & Mask3]; return halfCarryTableSub[index & Mask3];

View File

@ -8,10 +8,10 @@ namespace EightBit {
class LittleEndianProcessor : public Processor { class LittleEndianProcessor : public Processor {
public: public:
~LittleEndianProcessor() = default; virtual ~LittleEndianProcessor() {};
[[nodiscard]] register16_t peekWord(register16_t address) final; [[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
void pokeWord(register16_t address, register16_t value) final; void pokeWord(register16_t address, register16_t value) noexcept final;
protected: protected:
LittleEndianProcessor(Bus& memory); LittleEndianProcessor(Bus& memory);

View File

@ -7,8 +7,8 @@
namespace EightBit { namespace EightBit {
class Mapper { class Mapper {
public: public:
virtual ~Mapper() = default; virtual ~Mapper() {};
[[nodiscard]] virtual MemoryMapping mapping(uint16_t address) = 0; [[nodiscard]] virtual MemoryMapping mapping(uint16_t address) noexcept = 0;
}; };
} }

View File

@ -14,18 +14,21 @@ namespace EightBit {
// *) Possibly 'reference'able (Very likely if you've exposed 'poke') // *) Possibly 'reference'able (Very likely if you've exposed 'poke')
class Memory { class Memory {
public: public:
virtual ~Memory() = default; virtual ~Memory() {};
[[nodiscard]] virtual size_t size() const = 0; [[nodiscard]] virtual size_t size() const noexcept = 0;
[[nodiscard]] virtual uint8_t peek(uint16_t address) const = 0; [[nodiscard]] virtual uint8_t peek(uint16_t address) const noexcept = 0;
[[nodiscard]] virtual uint8_t& reference(uint16_t); [[nodiscard]] virtual uint8_t& reference(uint16_t) noexcept;
virtual int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0; virtual int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
virtual int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0; virtual int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
virtual int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0; virtual int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
protected: protected:
virtual void poke(uint16_t address, uint8_t value) = 0; virtual void poke(uint16_t address, uint8_t value) noexcept = 0;
private:
uint8_t m_delivered = 0xff;
}; };
} }

View File

@ -21,26 +21,26 @@ namespace EightBit {
return result; return result;
} }
~Processor() = default; virtual ~Processor() noexcept {}
[[nodiscard]] auto& PC() noexcept { return m_pc; } [[nodiscard]] constexpr auto& PC() noexcept { return m_pc; }
int run(int limit); int run(int limit);
virtual int step() = 0; virtual int step() = 0;
virtual int execute() = 0; virtual int execute() = 0;
int execute(uint8_t value); int execute(uint8_t value);
[[nodiscard]] virtual register16_t peekWord(register16_t address) = 0; [[nodiscard]] virtual register16_t peekWord(register16_t address) noexcept = 0;
virtual void pokeWord(register16_t address, register16_t value) = 0; virtual void pokeWord(register16_t address, register16_t value) noexcept = 0;
DECLARE_PIN_INPUT(RESET) DECLARE_PIN_INPUT(RESET)
DECLARE_PIN_INPUT(INT) DECLARE_PIN_INPUT(INT)
protected: protected:
Processor(Bus& memory); Processor(Bus& memory) noexcept;
[[nodiscard]] auto& opcode() noexcept { return m_opcode; } [[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; }
[[nodiscard]] auto& BUS() noexcept { return m_bus; } [[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; }
virtual void handleRESET(); virtual void handleRESET();
virtual void handleINT(); virtual void handleINT();

View File

@ -9,7 +9,7 @@ namespace EightBit {
public: public:
Ram(size_t size = 0) noexcept; Ram(size_t size = 0) noexcept;
[[nodiscard]] uint8_t& reference(uint16_t address) final; [[nodiscard]] uint8_t& reference(uint16_t address) noexcept final;
void poke(uint16_t address, uint8_t value) final; void poke(uint16_t address, uint8_t value) noexcept final;
}; };
} }

View File

@ -70,20 +70,20 @@ namespace EightBit {
} }
}; };
inline auto operator==(const register16_t lhs, const register16_t rhs) noexcept { [[nodiscard]] inline auto operator==(const register16_t lhs, const register16_t rhs) noexcept {
return lhs.word == rhs.word; return lhs.word == rhs.word;
} }
inline auto operator!=(const register16_t lhs, const register16_t rhs) noexcept { [[nodiscard]] inline auto operator!=(const register16_t lhs, const register16_t rhs) noexcept {
return !(lhs == rhs); return !(lhs == rhs);
} }
inline auto operator+(register16_t lhs, const register16_t rhs) noexcept { [[nodiscard]] inline auto operator+(register16_t lhs, const register16_t rhs) noexcept {
lhs += rhs; lhs += rhs;
return lhs; return lhs;
} }
inline auto operator-(register16_t lhs, const register16_t rhs) noexcept { [[nodiscard]] inline auto operator-(register16_t lhs, const register16_t rhs) noexcept {
lhs -= rhs; lhs -= rhs;
return lhs; return lhs;
} }

View File

@ -19,20 +19,20 @@ namespace EightBit {
[[nodiscard]] const auto& BYTES() const noexcept { return m_bytes; } [[nodiscard]] const auto& BYTES() const noexcept { return m_bytes; }
[[nodiscard]] auto& BYTES() noexcept { return m_bytes; } [[nodiscard]] auto& BYTES() noexcept { return m_bytes; }
void poke(uint16_t address, uint8_t value) override; void poke(uint16_t address, uint8_t value) noexcept override;
public: public:
static int load(std::ifstream& file, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1); static int load(std::ifstream& file, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
static int load(std::string path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1); static int load(std::string path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
Rom(size_t size = 0); Rom(size_t size = 0) noexcept;
[[nodiscard]] size_t size() const final; [[nodiscard]] size_t size() const noexcept final;
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final; int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) final; int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final; int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
[[nodiscard]] uint8_t peek(uint16_t address) const final; [[nodiscard]] uint8_t peek(uint16_t address) const noexcept final;
}; };
} }

View File

@ -15,7 +15,7 @@
#endif #endif
namespace EightBit { namespace EightBit {
template<class ConfigurationT, class BoardT> class TestHarness { template<class ConfigurationT, class BoardT> class TestHarness final {
public: public:
TestHarness(const ConfigurationT& configuration) TestHarness(const ConfigurationT& configuration)
: m_board(configuration) { : m_board(configuration) {

View File

@ -13,18 +13,18 @@ namespace EightBit {
// is being read. // is being read.
class UnusedMemory final : public Memory { class UnusedMemory final : public Memory {
public: public:
UnusedMemory(size_t size, uint8_t value); UnusedMemory(size_t size, uint8_t value) noexcept;
~UnusedMemory() = default; ~UnusedMemory() = default;
[[nodiscard]] size_t size() const final; [[nodiscard]] size_t size() const noexcept final;
[[nodiscard]] uint8_t peek(uint16_t address) const final; [[nodiscard]] uint8_t peek(uint16_t address) const noexcept final;
int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final; int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) final; int load(std::string path, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final; int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final;
protected: protected:
void poke(uint16_t address, uint8_t value) final; void poke(uint16_t address, uint8_t value) noexcept final;
private: private:
size_t m_size; size_t m_size;

View File

@ -47,13 +47,13 @@ EightBit::register16_t EightBit::BigEndianProcessor::popWord() {
return { low, high }; return { low, high };
} }
EightBit::register16_t EightBit::BigEndianProcessor::peekWord(const register16_t address) { EightBit::register16_t EightBit::BigEndianProcessor::peekWord(const register16_t address) noexcept {
const auto high = BUS().peek(address); const auto high = BUS().peek(address);
const auto low = BUS().peek(address + 1); const auto low = BUS().peek(address + 1);
return { low, high }; return { low, high };
} }
void EightBit::BigEndianProcessor::pokeWord(const register16_t address, const register16_t value) { void EightBit::BigEndianProcessor::pokeWord(const register16_t address, const register16_t value) noexcept {
BUS().poke(address, value.high); BUS().poke(address, value.high);
BUS().poke(address + 1, value.low); BUS().poke(address + 1, value.low);
} }

View File

@ -38,7 +38,7 @@ void EightBit::Bus::loadHexFile(const std::string path) {
} }
} }
uint8_t& EightBit::Bus::reference(const uint16_t address) { uint8_t& EightBit::Bus::reference(const uint16_t address) noexcept {
const auto mapped = mapping(address); const auto mapped = mapping(address);
const uint16_t offset = (address - mapped.begin) & mapped.mask; const uint16_t offset = (address - mapped.begin) & mapped.mask;
if (mapped.access == MemoryMapping::AccessLevel::ReadOnly) { if (mapped.access == MemoryMapping::AccessLevel::ReadOnly) {

View File

@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "../inc/InputOutput.h" #include "../inc/InputOutput.h"
#include <cassert>
#include <stdexcept> #include <stdexcept>
#include "../inc/Register.h" #include "../inc/Register.h"
@ -9,11 +10,12 @@ size_t EightBit::InputOutput::size() const noexcept {
return 0x100; return 0x100;
} }
uint8_t EightBit::InputOutput::peek(uint16_t) const { uint8_t EightBit::InputOutput::peek(uint16_t) const noexcept {
throw std::logic_error("Peek operation not allowed."); assert(false && "Peek operation not allowed.");
return 0xff;
} }
uint8_t& EightBit::InputOutput::reference(uint16_t address) { uint8_t& EightBit::InputOutput::reference(uint16_t address) noexcept {
const auto port = register16_t(address).low; const auto port = register16_t(address).low;
switch (accessType()) { switch (accessType()) {
case AccessType::Reading: case AccessType::Reading:
@ -21,8 +23,9 @@ uint8_t& EightBit::InputOutput::reference(uint16_t address) {
case AccessType::Writing: case AccessType::Writing:
return m_output.reference(port); return m_output.reference(port);
default: default:
throw std::logic_error("Unknown I/O access type."); assert(false && "Unknown I/O access type.");
} }
return m_delivered;
} }
int EightBit::InputOutput::load(std::ifstream&, int, int, int) { int EightBit::InputOutput::load(std::ifstream&, int, int, int) {
@ -37,6 +40,6 @@ int EightBit::InputOutput::load(const std::vector<uint8_t>&, int, int, int) {
throw std::logic_error("load operation not allowed."); throw std::logic_error("load operation not allowed.");
} }
void EightBit::InputOutput::poke(uint16_t, uint8_t) { void EightBit::InputOutput::poke(uint16_t, uint8_t) noexcept {
throw std::logic_error("Poke operation not allowed."); assert(false && "Poke operation not allowed.");
} }

View File

@ -47,13 +47,13 @@ EightBit::register16_t EightBit::LittleEndianProcessor::popWord() {
return { low, high }; return { low, high };
} }
EightBit::register16_t EightBit::LittleEndianProcessor::peekWord(const register16_t address) { EightBit::register16_t EightBit::LittleEndianProcessor::peekWord(const register16_t address) noexcept {
const auto low = BUS().peek(address); const auto low = BUS().peek(address);
const auto high = BUS().peek(address + 1); const auto high = BUS().peek(address + 1);
return { low, high }; return { low, high };
} }
void EightBit::LittleEndianProcessor::pokeWord(const register16_t address, const register16_t value) { void EightBit::LittleEndianProcessor::pokeWord(const register16_t address, const register16_t value) noexcept {
BUS().poke(address, value.low); BUS().poke(address, value.low);
BUS().poke(address + 1, value.high); BUS().poke(address + 1, value.high);
} }

View File

@ -1,8 +1,9 @@
#include "stdafx.h" #include "stdafx.h"
#include "../inc/Memory.h" #include "../inc/Memory.h"
#include <stdexcept> #include <cassert>
uint8_t& EightBit::Memory::reference(uint16_t) { uint8_t& EightBit::Memory::reference(uint16_t) noexcept {
throw std::logic_error("Reference operation not allowed."); assert(false && "Reference operation not allowed.");
return m_delivered;
} }

View File

@ -1,7 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "../inc/Processor.h" #include "../inc/Processor.h"
EightBit::Processor::Processor(Bus& bus) EightBit::Processor::Processor(Bus& bus) noexcept
: m_bus(bus) { : m_bus(bus) {
} }

View File

@ -4,10 +4,10 @@
EightBit::Ram::Ram(const size_t size) noexcept EightBit::Ram::Ram(const size_t size) noexcept
: Rom(size) {} : Rom(size) {}
uint8_t& EightBit::Ram::reference(const uint16_t address) { uint8_t& EightBit::Ram::reference(const uint16_t address) noexcept {
return BYTES()[address]; return BYTES()[address];
} }
void EightBit::Ram::poke(const uint16_t address, const uint8_t value) { void EightBit::Ram::poke(const uint16_t address, const uint8_t value) noexcept {
Rom::poke(address, value); Rom::poke(address, value);
} }

View File

@ -37,14 +37,14 @@ int EightBit::Rom::load(const std::string path, std::vector<uint8_t>& output, co
return size; return size;
} }
void EightBit::Rom::poke(const uint16_t address, const uint8_t value) { void EightBit::Rom::poke(const uint16_t address, const uint8_t value) noexcept {
BYTES()[address] = value; BYTES()[address] = value;
} }
EightBit::Rom::Rom(const size_t size) EightBit::Rom::Rom(const size_t size) noexcept
: m_bytes(size) {} : m_bytes(size) {}
size_t EightBit::Rom::size() const { size_t EightBit::Rom::size() const noexcept {
return m_bytes.size(); return m_bytes.size();
} }
@ -72,6 +72,6 @@ int EightBit::Rom::load(const std::vector<uint8_t>& bytes, const int writeOffset
return limit; return limit;
} }
uint8_t EightBit::Rom::peek(const uint16_t address) const { uint8_t EightBit::Rom::peek(const uint16_t address) const noexcept {
return BYTES()[address]; return BYTES()[address];
} }

View File

@ -1,14 +1,16 @@
#include "stdafx.h" #include "stdafx.h"
#include "../inc/UnusedMemory.h" #include "../inc/UnusedMemory.h"
EightBit::UnusedMemory::UnusedMemory(const size_t size, const uint8_t value) #include <cassert>
EightBit::UnusedMemory::UnusedMemory(const size_t size, const uint8_t value) noexcept
: m_size(size), m_value(value) {} : m_size(size), m_value(value) {}
size_t EightBit::UnusedMemory::size() const { size_t EightBit::UnusedMemory::size() const noexcept {
return m_size; return m_size;
} }
uint8_t EightBit::UnusedMemory::peek(uint16_t) const { uint8_t EightBit::UnusedMemory::peek(uint16_t) const noexcept {
return m_value; return m_value;
} }
@ -24,6 +26,6 @@ int EightBit::UnusedMemory::load(const std::vector<uint8_t>&, int, int, int) {
throw std::logic_error("load operation not allowed."); throw std::logic_error("load operation not allowed.");
} }
void EightBit::UnusedMemory::poke(uint16_t, uint8_t) { void EightBit::UnusedMemory::poke(uint16_t, uint8_t) noexcept {
throw std::logic_error("Poke operation not allowed."); assert(false && "Poke operation not allowed.");
} }