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;
protected:
virtual float fps() const = 0;
virtual bool useVsync() const = 0;
virtual float fps() const noexcept = 0;
virtual bool useVsync() const noexcept = 0;
virtual int windowWidth() const noexcept;
virtual int windowHeight() const noexcept;
@ -37,7 +37,7 @@ namespace Gaming {
virtual int rasterWidth() 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 update();

View File

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

View File

@ -19,20 +19,20 @@ EightBit::Intel8080::Intel8080(Bus& bus)
DEFINE_PIN_LEVEL_CHANGERS(DBIN, 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);
return af;
}
EightBit::register16_t& EightBit::Intel8080::BC() {
EightBit::register16_t& EightBit::Intel8080::BC() noexcept {
return bc;
}
EightBit::register16_t& EightBit::Intel8080::DE() {
EightBit::register16_t& EightBit::Intel8080::DE() noexcept {
return de;
}
EightBit::register16_t& EightBit::Intel8080::HL() {
EightBit::register16_t& EightBit::Intel8080::HL() noexcept {
return hl;
}

View File

@ -23,7 +23,7 @@ public:
virtual void initialise() final;
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 };
}

View File

@ -35,7 +35,7 @@ namespace Fuse {
EightBit::register16_t actual, EightBit::register16_t expected) const;
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 };
}

View File

@ -10,9 +10,9 @@ namespace EightBit {
namespace GameBoy {
class CharacterDefinition final {
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:
Ram& m_vram;

View File

@ -27,12 +27,12 @@ namespace EightBit {
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; }
void renderCurrentScanline();
void loadObjectAttributes();
void renderCurrentScanline() noexcept;
void loadObjectAttributes() noexcept;
private:
enum class tile_offset_t {
@ -48,35 +48,35 @@ namespace EightBit {
uint8_t m_control = 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(
int bgArea, int bgCharacters,
tile_offset_t offsetType,
int offsetX, int offsetY,
const std::array<int, 4>& palette);
const std::array<int, 4>& palette) noexcept;
void renderObjects();
void renderObjects() noexcept;
void renderSpriteTile(
int height,
int drawX, int drawY,
bool flipX, bool flipY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition);
const CharacterDefinition& definition) noexcept;
void renderBackgroundTile(
int drawX, int drawY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition);
const CharacterDefinition& definition) noexcept;
void renderTile(
int height,
int drawX, int drawY,
bool flipX, bool flipY, bool allowTransparencies,
const std::array<int, 4>& palette,
const CharacterDefinition& definition);
const CharacterDefinition& definition) noexcept;
};
}
}

View File

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

View File

@ -26,16 +26,16 @@ namespace EightBit {
Signal<LR35902> ExecutingInstruction;
Signal<LR35902> ExecutedInstruction;
[[nodiscard]] register16_t& AF() final;
[[nodiscard]] register16_t& BC() final;
[[nodiscard]] register16_t& DE() final;
[[nodiscard]] register16_t& HL() final;
[[nodiscard]] register16_t& AF() noexcept final;
[[nodiscard]] register16_t& BC() noexcept final;
[[nodiscard]] register16_t& DE() noexcept final;
[[nodiscard]] register16_t& HL() noexcept final;
bool& IME() noexcept { return m_ime; }
[[nodiscard]] uint8_t enabledInterrupts();
[[nodiscard]] uint8_t flaggedInterrupts();
[[nodiscard]] uint8_t maskedInterrupts();
[[nodiscard]] uint8_t enabledInterrupts() noexcept;
[[nodiscard]] uint8_t flaggedInterrupts() noexcept;
[[nodiscard]] uint8_t maskedInterrupts() noexcept;
Signal<EventArgs> MachineTicked;
@ -76,33 +76,33 @@ namespace EightBit {
[[nodiscard]] uint8_t R(int r);
void R(int r, uint8_t value);
[[nodiscard]] register16_t& RP(int rp);
[[nodiscard]] register16_t& RP2(int rp);
[[nodiscard]] register16_t& RP(int rp) noexcept;
[[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));
}
[[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));
}
[[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 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 decrement(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) noexcept;
void stop(bool value = true) noexcept { m_stopped = value; }
void start() noexcept { stop(false); }
[[nodiscard]] bool stopped() const noexcept { return m_stopped; }
void di();
void ei();
void di() noexcept;
void ei() noexcept;
void reti();
@ -113,33 +113,33 @@ namespace EightBit {
[[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 adc(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value);
static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static void compare(uint8_t& f, uint8_t operand, uint8_t value);
[[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) noexcept;
[[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) noexcept;
[[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) noexcept;
[[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 rrc(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t srl(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) noexcept;
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
static void bit(uint8_t& f, int n, uint8_t operand);
[[nodiscard]] static uint8_t res(int n, uint8_t operand);
[[nodiscard]] static uint8_t set(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) noexcept;
[[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 ccf(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t cpl(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) noexcept;
[[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>
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_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;

View File

@ -7,14 +7,14 @@
#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_oam(oam),
m_vram(vram),
m_colours(colours) {
}
void EightBit::GameBoy::Display::renderCurrentScanline() {
void EightBit::GameBoy::Display::renderCurrentScanline() noexcept {
m_scanLine = m_bus.IO().peek(IoRegisters::LY);
if (m_scanLine < RasterHeight) {
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 std::array<int, 4> palette = {
raw & 0b11,
@ -37,12 +37,12 @@ std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address)
return palette;
}
void EightBit::GameBoy::Display::loadObjectAttributes() {
void EightBit::GameBoy::Display::loadObjectAttributes() noexcept {
for (int i = 0; i < 40; ++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;
@ -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);
@ -105,7 +105,7 @@ void EightBit::GameBoy::Display::renderBackground() {
void EightBit::GameBoy::Display::renderBackground(
int bgArea, int bgCharacters, tile_offset_t offsetType,
int offsetX, int offsetY,
const std::array<int, 4>& palette) {
const std::array<int, 4>& palette) noexcept {
const int row = (m_scanLine - offsetY) / 8;
auto address = bgArea + row * BufferCharacterWidth;
@ -128,7 +128,7 @@ void EightBit::GameBoy::Display::renderSpriteTile(
const int drawX, const int drawY,
const bool flipX, const bool flipY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) {
const CharacterDefinition& definition) noexcept {
renderTile(
height,
drawX, drawY,
@ -140,7 +140,7 @@ void EightBit::GameBoy::Display::renderSpriteTile(
void EightBit::GameBoy::Display::renderBackgroundTile(
const int drawX, const int drawY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) {
const CharacterDefinition& definition) noexcept {
renderTile(
8,
drawX, drawY,
@ -154,7 +154,7 @@ void EightBit::GameBoy::Display::renderTile(
const int drawX, const int drawY,
const bool flipX, const bool flipY, const bool allowTransparencies,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) {
const CharacterDefinition& definition) noexcept {
const auto width = 8;

View File

@ -40,7 +40,7 @@ void EightBit::GameBoy::Bus::loadGameRom(const std::string path) {
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 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())
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);
return af;
}
EightBit::register16_t& EightBit::GameBoy::LR35902::BC() {
EightBit::register16_t& EightBit::GameBoy::LR35902::BC() noexcept {
return bc;
}
EightBit::register16_t& EightBit::GameBoy::LR35902::DE() {
EightBit::register16_t& EightBit::GameBoy::LR35902::DE() noexcept {
return de;
}
EightBit::register16_t& EightBit::GameBoy::LR35902::HL() {
EightBit::register16_t& EightBit::GameBoy::LR35902::HL() noexcept {
return hl;
}
@ -87,15 +87,15 @@ void EightBit::GameBoy::LR35902::ret() {
tickMachine();
}
void EightBit::GameBoy::LR35902::di() {
void EightBit::GameBoy::LR35902::di() noexcept {
IME() = false;
}
void EightBit::GameBoy::LR35902::ei() {
void EightBit::GameBoy::LR35902::ei() noexcept {
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);
const uint8_t result = operand + 1;
f = adjustZero<LR35902>(f, result);
@ -103,7 +103,7 @@ uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand)
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 = clearBit(f, HC, lowNibble(operand));
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) {
case 0b00:
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) {
case 0b00:
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 <= 7);
switch (flag) {
@ -249,7 +249,7 @@ EightBit::register16_t EightBit::GameBoy::LR35902::add(uint8_t& f, const registe
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 auto result = addition.low;
@ -263,11 +263,11 @@ uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const
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);
}
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 auto result = subtraction.low;
@ -281,11 +281,11 @@ uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand,
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);
}
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 = clearBit(f, CF | NF);
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;
}
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);
const uint8_t result = operand ^ value;
f = adjustZero<LR35902>(f, 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);
const uint8_t result = operand | value;
f = adjustZero<LR35902>(f, 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);
}
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);
const auto carry = operand & Bit7;
f = setBit(f, CF, carry);
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);
const auto carry = operand & Bit0;
f = setBit(f, CF, carry);
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);
const auto carry = f & CF;
f = setBit(f, CF, operand & Bit7);
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);
const auto carry = f & CF;
f = setBit(f, CF, operand & Bit0);
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 = setBit(f, CF, operand & Bit7);
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 = setBit(f, CF, operand & Bit0);
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);
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 = setBit(f, CF, operand & Bit0);
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 <= 7);
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);
}
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 <= 7);
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 <= 7);
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;
@ -407,30 +407,30 @@ uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) {
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);
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 = 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, CF, f & CF);
}
uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() {
uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() noexcept {
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);
}
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() {
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() noexcept {
return enabledInterrupts() & flaggedInterrupts();
}

View File

@ -34,13 +34,13 @@ namespace EightBit {
int execute() final;
[[nodiscard]] int step() final;
[[nodiscard]] auto& X() { return x; }
[[nodiscard]] auto& Y() { return y; }
[[nodiscard]] auto& A() { return a; }
[[nodiscard]] auto& S() { return s; }
[[nodiscard]] constexpr auto& X() noexcept { return x; }
[[nodiscard]] constexpr auto& Y() noexcept { return y; }
[[nodiscard]] constexpr auto& A() noexcept { return a; }
[[nodiscard]] constexpr auto& S() noexcept { return s; }
[[nodiscard]] auto& P() { return p; }
[[nodiscard]] const auto& P() const { return p; }
[[nodiscard]] constexpr auto& P() noexcept { return p; }
[[nodiscard]] constexpr const auto& P() const noexcept { return p; }
DECLARE_PIN_INPUT(NMI)
DECLARE_PIN_INPUT(SO)
@ -55,15 +55,15 @@ namespace EightBit {
void busWrite() final;
[[nodiscard]] uint8_t busRead() final;
[[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0);
[[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data);
[[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow);
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow);
[[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) noexcept;
[[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) noexcept;
[[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0);
[[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data);
[[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry);
[[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry);
[[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) noexcept;
[[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) noexcept;
private:
const uint8_t IRQvector = 0xfe; // IRQ vector
@ -111,29 +111,29 @@ namespace EightBit {
// Flag adjustment
void adjustZero(const uint8_t datum) { P() = clearBit(P(), ZF, datum); }
void adjustNegative(const uint8_t datum) { P() = setBit(P(), NF, datum & NF); }
void adjustZero(const uint8_t datum) noexcept { P() = clearBit(P(), ZF, datum); }
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);
adjustNegative(datum);
}
// Flag checking
[[nodiscard]] auto interruptMasked() const { return P() & IF; }
[[nodiscard]] auto decimal() const { return P() & DF; }
[[nodiscard]] auto interruptMasked() const noexcept { return P() & IF; }
[[nodiscard]] auto decimal() const noexcept { return P() & DF; }
[[nodiscard]] auto negative() const { return P() & NF; }
[[nodiscard]] auto zero() const { return P() & ZF; }
[[nodiscard]] auto overflow() const { return P() & VF; }
[[nodiscard]] auto carry() const { return P() & CF; }
[[nodiscard]] auto negative() const noexcept { return P() & NF; }
[[nodiscard]] auto zero() const noexcept { return P() & ZF; }
[[nodiscard]] auto overflow() const noexcept { return P() & VF; }
[[nodiscard]] auto carry() const noexcept { return P() & CF; }
// Miscellaneous
void branch(int condition);
[[nodiscard]] auto through(const uint8_t data) {
[[nodiscard]] auto through(const uint8_t data) noexcept {
adjustNZ(data);
return data;
}
@ -146,29 +146,29 @@ namespace EightBit {
// Instruction implementations
[[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data);
[[nodiscard]] uint8_t asl(uint8_t value);
void bit(uint8_t operand, uint8_t data);
void cmp(uint8_t first, uint8_t second);
[[nodiscard]] uint8_t dec(uint8_t value);
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data);
[[nodiscard]] uint8_t inc(uint8_t value);
[[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t asl(uint8_t value) noexcept;
void bit(uint8_t operand, uint8_t data) noexcept;
void cmp(uint8_t first, uint8_t second) noexcept;
[[nodiscard]] uint8_t dec(uint8_t value) noexcept;
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t inc(uint8_t value) noexcept;
void jsr();
[[nodiscard]] uint8_t lsr(uint8_t value);
[[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data);
[[nodiscard]] uint8_t lsr(uint8_t value) noexcept;
[[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data) noexcept;
void php();
void plp();
[[nodiscard]] uint8_t rol(uint8_t operand);
[[nodiscard]] uint8_t ror(uint8_t operand);
[[nodiscard]] uint8_t rol(uint8_t operand) noexcept;
[[nodiscard]] uint8_t ror(uint8_t operand) noexcept;
void rti();
void rts();
// Undocumented compound instructions
void anc(uint8_t value);
void arr(uint8_t value);
void asr(uint8_t value);
void axs(uint8_t value);
void anc(uint8_t value) noexcept;
void arr(uint8_t value) noexcept;
void asr(uint8_t value) noexcept;
void axs(uint8_t value) noexcept;
void dcp(uint8_t value);
void isb(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() {
auto address = Address_Absolute();
const auto address = Address_Absolute();
const auto page = address.high;
address += X();
return { address, page };
return { address + X(), page };
}
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;
address += Y();
return { address, page };
return { address + Y(), page };
}
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() {
auto address = Address_ZeroPageIndirect();
const auto address = Address_ZeroPageIndirect();
const auto page = address.high;
address += Y();
return { address, page };
return { address + Y(), page };
}
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() {
const auto[address, page] = Address_AbsoluteY();
const auto [address, page] = Address_AbsoluteY();
auto possible = getBytePaged(page, address.low);
if (UNLIKELY(page != address.high))
possible = memoryRead(address);
@ -524,13 +521,13 @@ void EightBit::MOS6502::branch(const int condition) {
const auto page = PC().high;
jump(destination);
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);
@ -542,16 +539,16 @@ uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) {
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);
}
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;
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;
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);
}
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());
adjustNZ(m_intermediate.low);
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);
}
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;
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;
}
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;
@ -605,36 +602,36 @@ uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) {
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);
}
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);
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);
adjustZero(operand & 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;
adjustNZ(result.low);
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);
}
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);
}
uint8_t EightBit::MOS6502::inc(const uint8_t value) {
uint8_t EightBit::MOS6502::inc(const uint8_t value) noexcept {
return through(value + 1);
}
@ -646,12 +643,12 @@ void EightBit::MOS6502::jsr() {
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);
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);
}
@ -663,14 +660,14 @@ void EightBit::MOS6502::plp() {
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();
P() = setBit(P(), CF, operand & Bit7);
const uint8_t result = (operand << 1) | carryIn;
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();
P() = setBit(P(), CF, operand & Bit0);
const uint8_t result = (operand >> 1) | (carryIn << 7);
@ -691,24 +688,24 @@ void EightBit::MOS6502::rts() {
// Undocumented compound instructions
void EightBit::MOS6502::anc(const uint8_t value) {
void EightBit::MOS6502::anc(const uint8_t value) noexcept {
A() = andr(A(), value);
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() = ror(A());
P() = setBit(P(), CF, A() & Bit6);
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() = 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));
P() = clearBit(P(), CF, m_intermediate.high);
}

View File

@ -23,7 +23,7 @@ public:
virtual void initialise() final;
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 };
}

View File

@ -13,6 +13,14 @@
namespace EightBit {
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:
enum StatusBits {
@ -89,13 +97,6 @@ namespace EightBit {
void halt() noexcept { --PC(); lowerHALT(); }
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:
// 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)
return { m_ram, 0x0000, EightBit::Chip::Mask16, EightBit::MemoryMapping::AccessLevel::ReadWrite };

View File

@ -26,7 +26,7 @@ public:
virtual void initialise() final;
protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
private:
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 };
}

View File

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

View File

@ -7,6 +7,49 @@
namespace EightBit {
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:
mc6850();
@ -58,7 +101,7 @@ namespace EightBit {
CR4 = 0b10000, // "
CR5 = 0b100000, // Transmit control
CR6 = 0b1000000, // "
CR7 = 0b10000000 // Receive control
CR7 = 0b10000000 // Receive control
};
// CR0 and CR1
@ -71,13 +114,13 @@ namespace EightBit {
// CR2, CR3 and CR4
enum WordSelect {
SevenEvenTwo = 0b000,
SevenEvenTwo = 0b000,
SevenOddTwo = 0b001,
SevenEvenOne = 0b010,
SevenEvenOne = 0b010,
SevenOddOne = 0b011,
EightTwo = 0b100,
EightOne = 0b101,
EightEvenOne = 0b110,
EightTwo = 0b100,
EightOne = 0b101,
EightEvenOne = 0b110,
EightOddOne = 0b111,
};
@ -219,48 +262,6 @@ namespace EightBit {
Signal<EventArgs> Receiving;
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:
void step();

View File

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

View File

@ -5,10 +5,10 @@ EightBit::Ricoh2A03::Ricoh2A03(Bus& 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);
}
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);
}

View File

@ -65,7 +65,7 @@ void Fuse::TestRunner::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();
if (memory)

View File

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

View File

@ -14,22 +14,44 @@ namespace EightBit {
class Bus;
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:
struct refresh_t {
bool high : 1;
uint8_t variable : 7;
refresh_t(const uint8_t value)
refresh_t(const uint8_t value) noexcept
: high(!!(value & Bit7)),
variable(value & Mask7)
{ }
operator uint8_t() const {
constexpr operator uint8_t() const noexcept {
return (high << 7) | variable;
}
auto& operator++() {
constexpr auto& operator++() noexcept {
++variable;
return *this;
}
@ -67,18 +89,18 @@ namespace EightBit {
int execute() final;
int step() final;
[[nodiscard]] register16_t& AF() final;
[[nodiscard]] register16_t& BC() final;
[[nodiscard]] register16_t& DE() final;
[[nodiscard]] register16_t& HL() final;
[[nodiscard]] register16_t& AF() noexcept final;
[[nodiscard]] register16_t& BC() noexcept final;
[[nodiscard]] register16_t& DE() noexcept final;
[[nodiscard]] register16_t& HL() noexcept final;
[[nodiscard]] auto& IX() { return m_ix; }
[[nodiscard]] auto& IXH() { return IX().high; }
[[nodiscard]] auto& IXL() { return IX().low; }
[[nodiscard]] auto& IX() noexcept { return m_ix; }
[[nodiscard]] auto& IXH() noexcept { return IX().high; }
[[nodiscard]] auto& IXL() noexcept { return IX().low; }
[[nodiscard]] auto& IY() { return m_iy; }
[[nodiscard]] auto& IYH() { return IY().high; }
[[nodiscard]] auto& IYL() { return IY().low; }
[[nodiscard]] auto& IY() noexcept { return m_iy; }
[[nodiscard]] auto& IYH() noexcept { return IY().high; }
[[nodiscard]] auto& IYL() noexcept { return IY().low; }
// ** From the Z80 CPU User Manual
// 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
// programmer. During refresh, the contents of the I Register are placed on the upper eight
// 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]] auto& IM() { return m_interruptMode; }
[[nodiscard]] auto& IFF1() { return m_iff1; }
[[nodiscard]] auto& IFF2() { return m_iff2; }
[[nodiscard]] constexpr auto& IV() noexcept { return iv; }
[[nodiscard]] constexpr auto& IM() noexcept { return m_interruptMode; }
[[nodiscard]] constexpr auto& IFF1() noexcept { return m_iff1; }
[[nodiscard]] constexpr auto& IFF2() noexcept { return m_iff2; }
void exx() { m_registerSet ^= 1; }
void exxAF() { m_accumulatorFlagsSet ^= 1; }
constexpr void exx() noexcept { m_registerSet ^= 1; }
constexpr void exxAF() noexcept { m_accumulatorFlagsSet ^= 1; }
[[nodiscard]] auto requestingIO() const { return lowered(IORQ()); }
[[nodiscard]] auto requestingMemory() const { return lowered(MREQ()); }
[[nodiscard]] constexpr auto requestingIO() const noexcept { return lowered(IORQ()); }
[[nodiscard]] constexpr auto requestingMemory() const noexcept { return lowered(MREQ()); }
[[nodiscard]] auto requestingRead() const { return lowered(RD()); }
[[nodiscard]] auto requestingWrite() const { 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)
[[nodiscard]] constexpr auto requestingRead() const noexcept { return lowered(RD()); }
[[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); }
protected:
void handleRESET() final;
@ -136,14 +145,6 @@ namespace EightBit {
int jrConditional(int condition) final;
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 };
std::array<std::array<register16_t, 3>, 2> m_registers;
@ -171,10 +172,10 @@ namespace EightBit {
void handleNMI();
void resetPrefixes();
void resetPrefixes() noexcept;
[[nodiscard]] auto displaced() const { return m_prefixDD || m_prefixFD; }
[[nodiscard]] uint16_t displacedAddress();
[[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; }
[[nodiscard]] uint16_t displacedAddress() noexcept;
void fetchDisplacement();
[[nodiscard]] uint8_t fetchOpCode();
@ -187,34 +188,34 @@ namespace EightBit {
typedef std::function<uint8_t(void)> reader_t;
void readInternalRegister(reader_t reader);
[[nodiscard]] register16_t& HL2();
[[nodiscard]] register16_t& RP(int rp);
[[nodiscard]] register16_t& RP2(int rp);
[[nodiscard]] register16_t& HL2() noexcept;
[[nodiscard]] register16_t& RP(int rp) noexcept;
[[nodiscard]] register16_t& RP2(int rp) noexcept;
[[nodiscard]] uint8_t R(int r);
void R(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 adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation);
[[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, int beforeNegative, int valueNegative, int afterNegative);
[[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, int beforeNegative, int valueNegative, int afterNegative);
[[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) noexcept;
[[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) noexcept;
[[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) 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 executeED(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 decrement(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) noexcept;
void di();
void ei();
void di() noexcept;
void ei() noexcept;
void retn();
void reti();
@ -228,33 +229,33 @@ namespace EightBit {
[[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]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value);
static void compare(uint8_t& f, uint8_t operand, uint8_t value);
[[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) noexcept;
[[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) noexcept;
[[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) noexcept;
[[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) noexcept;
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t sll(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t srl(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) noexcept;
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sll(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
static void bit(uint8_t& f, int n, uint8_t operand);
[[nodiscard]] static uint8_t res(int n, uint8_t operand);
[[nodiscard]] static uint8_t set(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) noexcept;
[[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 ccf(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t cpl(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) noexcept;
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand) noexcept;
void xhtl(register16_t& exchange);
@ -290,7 +291,7 @@ namespace EightBit {
void outd();
[[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 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 "L";
case 6:
if (m_prefixDD || m_prefixFD) {
if (m_prefixDD)
return "IX+%4%";
if (m_prefixFD)
return "IY+%4%";
}
else {
return "(HL)";
}
if (m_prefixDD)
return "IX+%4%";
if (m_prefixFD)
return "IY+%4%";
return "(HL)";
case 7:
return "A";
}

View File

@ -41,19 +41,19 @@ DEFINE_PIN_LEVEL_CHANGERS(IORQ, Z80);
DEFINE_PIN_LEVEL_CHANGERS(RD, 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];
}
EightBit::register16_t& EightBit::Z80::BC() {
EightBit::register16_t& EightBit::Z80::BC() noexcept {
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];
}
EightBit::register16_t& EightBit::Z80::HL() {
EightBit::register16_t& EightBit::Z80::HL() noexcept {
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;
}
void EightBit::Z80::ei() {
void EightBit::Z80::ei() noexcept {
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);
const uint8_t result = operand + 1;
f = adjustSZXY<Z80>(f, result);
@ -177,7 +177,7 @@ uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) {
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 = clearBit(f, HC, lowNibble(operand));
const uint8_t result = operand - 1;
@ -186,33 +186,33 @@ uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) {
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));
}
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));
}
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);
}
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);
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);
}
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);
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) {
case 0:
return !(f & ZF);
@ -328,7 +328,7 @@ EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand
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 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;
}
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);
}
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 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;
}
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);
f = adjustXY<Z80>(f, 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);
}
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 = clearBit(f, CF | NF);
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;
}
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);
const uint8_t result = operand ^ value;
f = adjustSZPXY<Z80>(f, 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);
const uint8_t result = operand | value;
f = adjustSZPXY<Z80>(f, 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);
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);
const auto carry = operand & Bit7;
f = setBit(f, CF, carry);
@ -408,7 +408,7 @@ uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) {
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);
const auto carry = operand & Bit0;
f = setBit(f, CF, carry);
@ -417,7 +417,7 @@ uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) {
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);
const auto carry = f & CF;
f = setBit(f, CF, operand & Bit7);
@ -426,7 +426,7 @@ uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) {
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);
const auto carry = f & CF;
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 = setBit(f, CF, operand & Bit7);
const uint8_t result = operand << 1;
@ -445,7 +445,7 @@ uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) {
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 = setBit(f, CF, operand & Bit0);
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;
}
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 = setBit(f, CF, operand & Bit7);
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;
}
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 = setBit(f, CF, operand & Bit0);
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;
}
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 = clearBit(f, NF);
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);
}
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));
}
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));
}
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, CF, operand);
@ -502,7 +502,7 @@ uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) {
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 highAdjust = (f & CF) || (operand > 0x99);
@ -527,20 +527,20 @@ uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) {
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);
const uint8_t result = ~operand;
f = adjustXY<Z80>(f, 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 = clearBit(f, HC | NF);
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);
const auto carry = f & CF;
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;
}
//
uint16_t EightBit::Z80::displacedAddress() {
uint16_t EightBit::Z80::displacedAddress() noexcept {
return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
}
@ -851,7 +851,7 @@ void EightBit::Z80::readInternalRegister(reader_t reader) {
tick();
}
EightBit::register16_t& EightBit::Z80::HL2() {
EightBit::register16_t& EightBit::Z80::HL2() noexcept {
if (UNLIKELY(m_prefixDD))
return IX();
if (UNLIKELY(m_prefixFD))
@ -859,7 +859,7 @@ EightBit::register16_t& EightBit::Z80::HL2() {
return HL();
}
EightBit::register16_t& EightBit::Z80::RP(const int rp) {
EightBit::register16_t& EightBit::Z80::RP(const int rp) noexcept {
switch (rp) {
case 0b00:
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) {
case 0b00:
return BC();

View File

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

View File

@ -12,7 +12,7 @@
namespace EightBit {
class Bus : public Mapper {
public:
virtual ~Bus() = default;
virtual ~Bus() {};
Signal<EventArgs> WritingByte;
Signal<EventArgs> WrittenByte;
@ -26,12 +26,12 @@ namespace EightBit {
[[nodiscard]] auto DATA() const noexcept { return m_data; }
[[nodiscard]] auto& DATA() noexcept { return m_data; }
[[nodiscard]] auto peek() { return reference(); }
[[nodiscard]] virtual uint8_t peek(const uint16_t address) { return reference(address); }
[[nodiscard]] auto peek(const register16_t address) { return peek(address.word); }
void poke(const uint8_t value) { reference() = value; }
virtual void poke(const uint16_t address, const uint8_t value) { reference(address) = value; }
void poke(const register16_t address, const uint8_t value) { poke(address.word, value); }
[[nodiscard]] auto peek() noexcept { return reference(); }
[[nodiscard]] virtual uint8_t peek(const uint16_t address) noexcept { return reference(address); }
[[nodiscard]] auto peek(const register16_t address) noexcept { return peek(address.word); }
void poke(const uint8_t value) noexcept { reference() = 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) noexcept { poke(address.word, value); }
[[nodiscard]] uint8_t read();
template<class T> [[nodiscard]] auto read(const T address) {
@ -52,9 +52,9 @@ namespace EightBit {
virtual void initialise() = 0;
protected:
[[nodiscard]] uint8_t& reference(uint16_t address);
[[nodiscard]] auto& reference(const register16_t address) { return reference(address.word); }
[[nodiscard]] uint8_t& reference() { return reference(ADDRESS()); }
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept;
[[nodiscard]] auto& reference(const register16_t address) noexcept { return reference(address.word); }
[[nodiscard]] uint8_t& reference() noexcept { return reference(ADDRESS()); }
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 bool condition) noexcept { return setBit(input, which, !condition); }
[[nodiscard]] static constexpr auto highNibble(const int value) { return value >> 4; }
[[nodiscard]] static constexpr auto lowNibble(const int value) { return value & Mask4; }
[[nodiscard]] static constexpr auto highNibble(const int value) noexcept { return value >> 4; }
[[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 lowerNibble(const int value) { return lowNibble(value); }
[[nodiscard]] static constexpr auto higherNibble(const int value) noexcept { return value & 0xf0; }
[[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 demoteNibble(const int value) { return highNibble(value); }
[[nodiscard]] static constexpr auto promoteNibble(const int value) noexcept { return value << 4; }
[[nodiscard]] static constexpr auto demoteNibble(const int value) noexcept { return highNibble(value); }
~Chip() = default;
virtual ~Chip() {}
protected:
Chip() = default;
Chip() noexcept = default;
};
}

View File

@ -7,16 +7,18 @@
namespace EightBit {
class ClockedChip : public Chip {
public:
~ClockedChip() = default;
virtual ~ClockedChip() noexcept {};
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();
protected:
ClockedChip() noexcept = default;
void resetCycles() noexcept;
private:

View File

@ -48,11 +48,11 @@
template <class T> class _Activate ## name final { \
T& m_parent; \
public: \
_Activate ## name(T& parent) \
_Activate ## name(T& parent) noexcept \
: m_parent(parent) { \
m_parent. on ## name(); \
} \
~_Activate ## name() { \
~_Activate ## name() noexcept { \
m_parent. off ## name(); \
} \
};
@ -66,10 +66,10 @@
#define DECLARE_PIN(name, visibility) \
public: \
DECLARE_PIN_SIGNALS(name) \
[[nodiscard]] PinLevel& name () noexcept { \
[[nodiscard]] constexpr auto& name () noexcept { \
return m_## name ## _Line; \
} \
[[nodiscard]] const PinLevel& name () const noexcept { \
[[nodiscard]] constexpr const auto& name () const noexcept { \
return m_## name ## _Line; \
} \
visibility : \
@ -92,22 +92,23 @@ namespace EightBit {
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)
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:
Device() noexcept = default;
Device() noexcept {};
};
}

View File

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

View File

@ -6,6 +6,6 @@ namespace EightBit {
static EventArgs m_empty;
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 };
[[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::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;
[[nodiscard]] const AccessType& accessType() const noexcept { return m_access; }
[[nodiscard]] AccessType& accessType() noexcept { return m_access; }
[[nodiscard]] constexpr const auto& accessType() const 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;
return reference(port);
}
[[nodiscard]] auto readInputPort(uint8_t port) { return readPort(port, AccessType::Reading); }
[[nodiscard]] auto readOutputPort(uint8_t port) { return readPort(port, AccessType::Writing); }
[[nodiscard]] auto readInputPort(uint8_t port) noexcept { return readPort(port, AccessType::Reading); }
[[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;
reference(port) = value;
}
void writeInputPort(uint8_t port, uint8_t value) { writePort(port, value, AccessType::Reading); }
void writeOutputPort(uint8_t port, uint8_t value) { writePort(port, value, AccessType::Writing); }
void writeInputPort(uint8_t port, uint8_t value) noexcept { writePort(port, value, AccessType::Reading); }
void writeOutputPort(uint8_t port, uint8_t value) noexcept { writePort(port, value, AccessType::Writing); }
protected:
void poke(uint16_t address, uint8_t value) override;
void poke(uint16_t address, uint8_t value) noexcept override;
private:
Ram m_input = 0x100;
Ram m_output = 0x100;
uint8_t m_delivered = 0xff;
AccessType m_access = AccessType::Unknown;
};

View File

@ -23,9 +23,9 @@ namespace EightBit {
int p = 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
y = (opcode & 0b00111000) >> 3; // 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];
}
[[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]] auto& A() { return AF().high; }
[[nodiscard]] auto& F() { return AF().low; }
[[nodiscard]] virtual register16_t& AF() noexcept = 0;
[[nodiscard]] auto& A() noexcept { return AF().high; }
[[nodiscard]] auto& F() noexcept { return AF().low; }
[[nodiscard]] virtual register16_t& BC() = 0;
[[nodiscard]] auto& B() { return BC().high; }
[[nodiscard]] auto& C() { return BC().low; }
[[nodiscard]] virtual register16_t& BC() noexcept = 0;
[[nodiscard]] auto& B() noexcept { return BC().high; }
[[nodiscard]] auto& C() noexcept { return BC().low; }
[[nodiscard]] virtual register16_t& DE() = 0;
[[nodiscard]] auto& D() { return DE().high; }
[[nodiscard]] auto& E() { return DE().low; }
[[nodiscard]] virtual register16_t& DE() noexcept = 0;
[[nodiscard]] auto& D() noexcept { return DE().high; }
[[nodiscard]] auto& E() noexcept { return DE().low; }
[[nodiscard]] virtual register16_t& HL() = 0;
[[nodiscard]] auto& H() { return HL().high; }
[[nodiscard]] auto& L() { return HL().low; }
[[nodiscard]] virtual register16_t& HL() noexcept = 0;
[[nodiscard]] auto& H() noexcept { return HL().high; }
[[nodiscard]] auto& L() noexcept { return HL().low; }
DECLARE_PIN_OUTPUT(HALT)
protected:
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);
}
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);
}
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));
}
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);
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);
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);
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);
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);
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);
}
@ -114,7 +114,7 @@ namespace EightBit {
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 } };
const auto index = buildHalfCarryIndex(before, value, calculation);
return halfCarryTableSub[index & Mask3];

View File

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

View File

@ -7,8 +7,8 @@
namespace EightBit {
class Mapper {
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')
class Memory {
public:
virtual ~Memory() = default;
virtual ~Memory() {};
[[nodiscard]] virtual size_t size() const = 0;
[[nodiscard]] virtual uint8_t peek(uint16_t address) const = 0;
[[nodiscard]] virtual size_t size() const noexcept = 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::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;
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;
}
~Processor() = default;
virtual ~Processor() noexcept {}
[[nodiscard]] auto& PC() noexcept { return m_pc; }
[[nodiscard]] constexpr auto& PC() noexcept { return m_pc; }
int run(int limit);
virtual int step() = 0;
virtual int execute() = 0;
int execute(uint8_t value);
[[nodiscard]] virtual register16_t peekWord(register16_t address) = 0;
virtual void pokeWord(register16_t address, register16_t value) = 0;
[[nodiscard]] virtual register16_t peekWord(register16_t address) noexcept = 0;
virtual void pokeWord(register16_t address, register16_t value) noexcept = 0;
DECLARE_PIN_INPUT(RESET)
DECLARE_PIN_INPUT(INT)
protected:
Processor(Bus& memory);
Processor(Bus& memory) noexcept;
[[nodiscard]] auto& opcode() noexcept { return m_opcode; }
[[nodiscard]] auto& BUS() noexcept { return m_bus; }
[[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; }
[[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; }
virtual void handleRESET();
virtual void handleINT();

View File

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

View File

@ -19,20 +19,20 @@ namespace EightBit {
[[nodiscard]] const auto& BYTES() const 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:
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);
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::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;
[[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
namespace EightBit {
template<class ConfigurationT, class BoardT> class TestHarness {
template<class ConfigurationT, class BoardT> class TestHarness final {
public:
TestHarness(const ConfigurationT& configuration)
: m_board(configuration) {

View File

@ -13,18 +13,18 @@ namespace EightBit {
// is being read.
class UnusedMemory final : public Memory {
public:
UnusedMemory(size_t size, uint8_t value);
UnusedMemory(size_t size, uint8_t value) noexcept;
~UnusedMemory() = default;
[[nodiscard]] size_t size() const final;
[[nodiscard]] uint8_t peek(uint16_t address) const final;
[[nodiscard]] size_t size() const noexcept 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::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;
protected:
void poke(uint16_t address, uint8_t value) final;
void poke(uint16_t address, uint8_t value) noexcept final;
private:
size_t m_size;

View File

@ -47,13 +47,13 @@ EightBit::register16_t EightBit::BigEndianProcessor::popWord() {
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 low = BUS().peek(address + 1);
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 + 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 uint16_t offset = (address - mapped.begin) & mapped.mask;
if (mapped.access == MemoryMapping::AccessLevel::ReadOnly) {

View File

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

View File

@ -47,13 +47,13 @@ EightBit::register16_t EightBit::LittleEndianProcessor::popWord() {
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 high = BUS().peek(address + 1);
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 + 1, value.high);
}

View File

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

View File

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

View File

@ -4,10 +4,10 @@
EightBit::Ram::Ram(const size_t size) noexcept
: Rom(size) {}
uint8_t& EightBit::Ram::reference(const uint16_t address) {
uint8_t& EightBit::Ram::reference(const uint16_t address) noexcept {
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);
}

View File

@ -37,14 +37,14 @@ int EightBit::Rom::load(const std::string path, std::vector<uint8_t>& output, co
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;
}
EightBit::Rom::Rom(const size_t size)
EightBit::Rom::Rom(const size_t size) noexcept
: m_bytes(size) {}
size_t EightBit::Rom::size() const {
size_t EightBit::Rom::size() const noexcept {
return m_bytes.size();
}
@ -72,6 +72,6 @@ int EightBit::Rom::load(const std::vector<uint8_t>& bytes, const int writeOffset
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];
}

View File

@ -1,14 +1,16 @@
#include "stdafx.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) {}
size_t EightBit::UnusedMemory::size() const {
size_t EightBit::UnusedMemory::size() const noexcept {
return m_size;
}
uint8_t EightBit::UnusedMemory::peek(uint16_t) const {
uint8_t EightBit::UnusedMemory::peek(uint16_t) const noexcept {
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.");
}
void EightBit::UnusedMemory::poke(uint16_t, uint8_t) {
throw std::logic_error("Poke operation not allowed.");
void EightBit::UnusedMemory::poke(uint16_t, uint8_t) noexcept {
assert(false && "Poke operation not allowed.");
}