2017-06-11 08:45:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
2017-06-19 17:08:13 +00:00
|
|
|
#include <cstdint>
|
|
|
|
#include <array>
|
|
|
|
|
2018-08-17 20:53:49 +00:00
|
|
|
#include "LittleEndianProcessor.h"
|
2017-10-22 20:24:28 +00:00
|
|
|
#include "Register.h"
|
2019-01-14 02:10:17 +00:00
|
|
|
#include "EventArgs.h"
|
|
|
|
#include "Signal.h"
|
2017-11-20 19:17:49 +00:00
|
|
|
#include "EightBitCompilerDefinitions.h"
|
2017-11-04 23:15:55 +00:00
|
|
|
|
2021-12-27 14:24:38 +00:00
|
|
|
#define NON_CONST_ACCESSOR(accessor, type) \
|
2022-01-17 19:10:15 +00:00
|
|
|
[[nodiscard]] constexpr auto& accessor() noexcept { \
|
2021-12-27 14:24:38 +00:00
|
|
|
const auto& consted = *this; \
|
|
|
|
const auto& reference = consted.accessor(); \
|
|
|
|
return const_cast<type&>(reference); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define NON_CONST_REGISTOR_ACCESSOR(accessor) \
|
|
|
|
NON_CONST_ACCESSOR(accessor, register16_t)
|
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
namespace EightBit {
|
2020-04-06 22:11:21 +00:00
|
|
|
|
|
|
|
class Bus;
|
|
|
|
|
2018-11-27 22:36:54 +00:00
|
|
|
class IntelProcessor : public LittleEndianProcessor {
|
2017-06-11 08:45:34 +00:00
|
|
|
public:
|
2017-07-21 12:33:17 +00:00
|
|
|
struct opcode_decoded_t {
|
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
int x = 0;
|
|
|
|
int y = 0;
|
|
|
|
int z = 0;
|
|
|
|
int p = 0;
|
|
|
|
int q = 0;
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
constexpr opcode_decoded_t() noexcept {}
|
2017-07-21 12:33:17 +00:00
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
constexpr opcode_decoded_t(const uint8_t opcode) noexcept {
|
2017-07-21 12:33:17 +00:00
|
|
|
x = (opcode & 0b11000000) >> 6; // 0 - 3
|
|
|
|
y = (opcode & 0b00111000) >> 3; // 0 - 7
|
|
|
|
z = (opcode & 0b00000111); // 0 - 7
|
|
|
|
p = (y & 0b110) >> 1; // 0 - 3
|
|
|
|
q = (y & 1); // 0 - 1
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-01-13 10:24:21 +00:00
|
|
|
IntelProcessor(const IntelProcessor& rhs) noexcept;
|
|
|
|
bool operator==(const IntelProcessor& rhs) const noexcept;
|
2021-12-27 14:24:38 +00:00
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] constexpr const auto& getDecodedOpcode(const size_t i) const noexcept {
|
2020-05-03 19:29:18 +00:00
|
|
|
return m_decodedOpcodes[i];
|
2017-07-21 12:33:17 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] constexpr auto& MEMPTR() noexcept { return m_memptr; }
|
2021-12-27 14:24:38 +00:00
|
|
|
[[nodiscard]] constexpr auto MEMPTR() const noexcept { return m_memptr; }
|
2018-03-18 22:40:23 +00:00
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] constexpr auto& SP() noexcept { return m_sp; }
|
2021-12-27 14:24:38 +00:00
|
|
|
[[nodiscard]] register16_t SP() const noexcept { return m_sp; }
|
2017-07-07 08:27:06 +00:00
|
|
|
|
2021-12-27 14:24:38 +00:00
|
|
|
[[nodiscard]] virtual const register16_t& AF() const noexcept = 0;
|
|
|
|
NON_CONST_REGISTOR_ACCESSOR(AF);
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] auto& A() noexcept { return AF().high; }
|
|
|
|
[[nodiscard]] auto& F() noexcept { return AF().low; }
|
2017-06-16 12:52:10 +00:00
|
|
|
|
2021-12-27 14:24:38 +00:00
|
|
|
[[nodiscard]] virtual const register16_t& BC() const noexcept = 0;
|
|
|
|
NON_CONST_REGISTOR_ACCESSOR(BC);
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] auto& B() noexcept { return BC().high; }
|
|
|
|
[[nodiscard]] auto& C() noexcept { return BC().low; }
|
2017-06-16 12:52:10 +00:00
|
|
|
|
2021-12-27 14:24:38 +00:00
|
|
|
[[nodiscard]] virtual const register16_t& DE() const noexcept = 0;
|
|
|
|
NON_CONST_REGISTOR_ACCESSOR(DE);
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] auto& D() noexcept { return DE().high; }
|
|
|
|
[[nodiscard]] auto& E() noexcept { return DE().low; }
|
2017-06-16 12:52:10 +00:00
|
|
|
|
2021-12-27 14:24:38 +00:00
|
|
|
[[nodiscard]] virtual const register16_t& HL() const noexcept = 0;
|
|
|
|
NON_CONST_REGISTOR_ACCESSOR(HL);
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] auto& H() noexcept { return HL().high; }
|
|
|
|
[[nodiscard]] auto& L() noexcept { return HL().low; }
|
2017-06-16 12:52:10 +00:00
|
|
|
|
2019-11-19 23:05:27 +00:00
|
|
|
DECLARE_PIN_OUTPUT(HALT)
|
2019-01-14 23:17:54 +00:00
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
protected:
|
2017-09-06 12:22:23 +00:00
|
|
|
IntelProcessor(Bus& bus);
|
2017-06-11 08:45:34 +00:00
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustSign(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
return setBit(f, T::SF, value & T::SF);
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustZero(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
return clearBit(f, T::ZF, value);
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustParity(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
return clearBit(f, T::PF, PARITY(value));
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZ(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
const auto intermediate = adjustSign<T>(f, value);
|
|
|
|
return adjustZero<T>(intermediate, value);
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZP(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
const auto intermediate = adjustSZ<T>(f, value);
|
|
|
|
return adjustParity<T>(intermediate, value);
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustXY(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
const auto intermediate = setBit(f, T::XF, value & T::XF);
|
|
|
|
return setBit(intermediate, T::YF, value & T::YF);
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZPXY(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
const auto intermediate = adjustSZP<T>(f, value);
|
|
|
|
return adjustXY<T>(intermediate, value);
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class T> [[nodiscard]] static constexpr uint8_t adjustSZXY(uint8_t f, const uint8_t value) noexcept {
|
2019-11-09 18:58:23 +00:00
|
|
|
const auto intermediate = adjustSZ<T>(f, value);
|
|
|
|
return adjustXY<T>(intermediate, value);
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] static constexpr auto buildHalfCarryIndex(const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
2017-06-11 08:45:34 +00:00
|
|
|
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
|
|
|
}
|
|
|
|
|
2021-08-23 08:44:48 +00:00
|
|
|
[[nodiscard]] static constexpr auto calculateHalfCarry(const std::array<int, 8>& table, const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
2017-10-23 23:04:13 +00:00
|
|
|
const auto index = buildHalfCarryIndex(before, value, calculation);
|
2021-08-23 08:44:48 +00:00
|
|
|
return table[index & Mask3];
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] static constexpr auto calculateHalfCarryAdd(const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
|
|
|
return calculateHalfCarry(m_halfCarryTableAdd, before, value, calculation);
|
2017-06-11 08:45:34 +00:00
|
|
|
}
|
|
|
|
|
2021-07-18 13:28:40 +00:00
|
|
|
[[nodiscard]] static constexpr auto calculateHalfCarrySub(const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
2021-08-23 08:44:48 +00:00
|
|
|
return calculateHalfCarry(m_halfCarryTableSub, before, value, calculation);
|
2017-06-11 08:45:34 +00:00
|
|
|
}
|
|
|
|
|
2024-01-13 10:24:21 +00:00
|
|
|
void handleRESET() override;
|
2019-01-14 02:10:17 +00:00
|
|
|
|
2024-01-13 10:24:21 +00:00
|
|
|
void push(uint8_t value) final;
|
|
|
|
[[nodiscard]] uint8_t pop() final;
|
2017-06-18 17:14:39 +00:00
|
|
|
|
2017-06-11 20:08:40 +00:00
|
|
|
//
|
|
|
|
|
2024-01-13 10:24:21 +00:00
|
|
|
[[nodiscard]] register16_t getWord() final;
|
|
|
|
void setWord(register16_t value) final;
|
2017-06-12 13:33:00 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
|
2024-01-13 10:24:21 +00:00
|
|
|
virtual void restart(uint8_t address);
|
|
|
|
virtual int callConditional(int condition);
|
|
|
|
virtual int jumpConditional(int condition);
|
|
|
|
virtual int returnConditional(int condition);
|
2022-01-17 19:10:15 +00:00
|
|
|
virtual void jr(int8_t offset) noexcept;
|
2024-01-13 10:24:21 +00:00
|
|
|
virtual int jrConditional(int condition);
|
|
|
|
void ret() override;
|
2017-06-11 20:08:40 +00:00
|
|
|
|
2024-01-13 10:24:21 +00:00
|
|
|
void resetWorkingRegisters() noexcept;
|
2021-12-27 14:24:38 +00:00
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
private:
|
2021-08-23 08:44:48 +00:00
|
|
|
static std::array<int, 8> m_halfCarryTableAdd;
|
|
|
|
static std::array<int, 8> m_halfCarryTableSub;
|
|
|
|
|
2017-07-21 12:33:17 +00:00
|
|
|
std::array<opcode_decoded_t, 0x100> m_decodedOpcodes;
|
2018-11-16 23:49:52 +00:00
|
|
|
register16_t m_sp = Mask16;
|
2018-06-15 23:55:32 +00:00
|
|
|
register16_t m_memptr;
|
2017-06-11 08:45:34 +00:00
|
|
|
};
|
2017-11-30 23:19:17 +00:00
|
|
|
}
|