2017-06-11 08:45:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
2017-06-19 17:08:13 +00:00
|
|
|
#include <cstdint>
|
|
|
|
#include <array>
|
|
|
|
|
2017-11-05 12:47:42 +00:00
|
|
|
#include "Bus.h"
|
2018-08-17 20:53:49 +00:00
|
|
|
#include "LittleEndianProcessor.h"
|
2017-10-22 20:24:28 +00:00
|
|
|
#include "Register.h"
|
2017-06-11 08:45:34 +00:00
|
|
|
|
2017-11-20 19:17:49 +00:00
|
|
|
#include "EightBitCompilerDefinitions.h"
|
2017-11-04 23:15:55 +00:00
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
namespace EightBit {
|
2018-08-17 20:53:49 +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;
|
|
|
|
|
2018-08-07 22:06:15 +00:00
|
|
|
opcode_decoded_t() noexcept {}
|
2017-07-21 12:33:17 +00:00
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
opcode_decoded_t(const uint8_t opcode) {
|
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
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const opcode_decoded_t& getDecodedOpcode(const int i) const {
|
|
|
|
return m_decodedOpcodes[i];
|
|
|
|
}
|
|
|
|
|
2018-03-18 22:40:23 +00:00
|
|
|
register16_t& MEMPTR() { return m_memptr; }
|
|
|
|
|
2017-11-03 22:05:01 +00:00
|
|
|
register16_t& SP() { return m_sp; }
|
2017-07-07 08:27:06 +00:00
|
|
|
|
2017-06-16 12:52:10 +00:00
|
|
|
virtual register16_t& AF() = 0;
|
|
|
|
uint8_t& A() { return AF().high; }
|
|
|
|
uint8_t& F() { return AF().low; }
|
|
|
|
|
|
|
|
virtual register16_t& BC() = 0;
|
|
|
|
uint8_t& B() { return BC().high; }
|
|
|
|
uint8_t& C() { return BC().low; }
|
|
|
|
|
|
|
|
virtual register16_t& DE() = 0;
|
|
|
|
uint8_t& D() { return DE().high; }
|
|
|
|
uint8_t& E() { return DE().low; }
|
|
|
|
|
|
|
|
virtual register16_t& HL() = 0;
|
|
|
|
uint8_t& H() { return HL().high; }
|
|
|
|
uint8_t& L() { return HL().low; }
|
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
protected:
|
2017-09-06 12:22:23 +00:00
|
|
|
IntelProcessor(Bus& bus);
|
2017-11-30 23:15:40 +00:00
|
|
|
virtual ~IntelProcessor() = default;
|
2017-06-11 08:45:34 +00:00
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
virtual void reset() override;
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustSign(uint8_t& f, const uint8_t value) {
|
2017-06-22 15:57:38 +00:00
|
|
|
setFlag(f, T::SF, value & T::SF);
|
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustZero(uint8_t& f, const uint8_t value) {
|
2017-06-22 15:57:38 +00:00
|
|
|
clearFlag(f, T::ZF, value);
|
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustParity(uint8_t& f, const uint8_t value) {
|
2017-12-12 23:12:45 +00:00
|
|
|
clearFlag(f, T::PF, PARITY(value));
|
2017-06-22 15:57:38 +00:00
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustSZ(uint8_t& f, const uint8_t value) {
|
2017-06-22 15:57:38 +00:00
|
|
|
adjustSign<T>(f, value);
|
|
|
|
adjustZero<T>(f, value);
|
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustSZP(uint8_t& f, const uint8_t value) {
|
2017-06-22 15:57:38 +00:00
|
|
|
adjustSZ<T>(f, value);
|
|
|
|
adjustParity<T>(f, value);
|
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustXY(uint8_t& f, const uint8_t value) {
|
2017-06-22 15:57:38 +00:00
|
|
|
setFlag(f, T::XF, value & T::XF);
|
|
|
|
setFlag(f, T::YF, value & T::YF);
|
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustSZPXY(uint8_t& f, const uint8_t value) {
|
2017-06-22 15:57:38 +00:00
|
|
|
adjustSZP<T>(f, value);
|
|
|
|
adjustXY<T>(f, value);
|
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
template<class T> static void adjustSZXY(uint8_t& f, const uint8_t value) {
|
2017-06-22 15:57:38 +00:00
|
|
|
adjustSZ<T>(f, value);
|
|
|
|
adjustXY<T>(f, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
static int buildHalfCarryIndex(const uint8_t before, const uint8_t value, const int calculation) {
|
2017-06-11 08:45:34 +00:00
|
|
|
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
static bool calculateHalfCarryAdd(const uint8_t before, const uint8_t value, const int calculation) {
|
2017-06-19 12:53:00 +00:00
|
|
|
static std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
|
2017-10-23 23:04:13 +00:00
|
|
|
const auto index = buildHalfCarryIndex(before, value, calculation);
|
2017-06-13 22:43:21 +00:00
|
|
|
return m_halfCarryTableAdd[index & Mask3];
|
2017-06-11 08:45:34 +00:00
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
static bool calculateHalfCarrySub(const uint8_t before, const uint8_t value, const int calculation) {
|
2017-06-19 12:53:00 +00:00
|
|
|
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
|
2017-10-23 23:04:13 +00:00
|
|
|
const auto index = buildHalfCarryIndex(before, value, calculation);
|
2017-06-13 22:43:21 +00:00
|
|
|
return m_halfCarryTableSub[index & Mask3];
|
2017-06-11 08:45:34 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 15:13:26 +00:00
|
|
|
virtual void push(uint8_t value) final;
|
|
|
|
virtual uint8_t pop() final;
|
2017-06-18 17:14:39 +00:00
|
|
|
|
2017-06-11 20:08:40 +00:00
|
|
|
//
|
|
|
|
|
2018-08-17 20:53:49 +00:00
|
|
|
virtual register16_t getWord() final;
|
|
|
|
virtual void setWord(register16_t value) final;
|
2017-06-12 13:33:00 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
void restart(const uint8_t address) {
|
2018-08-17 12:59:59 +00:00
|
|
|
call(MEMPTR() = register16_t(address, 0));
|
2017-06-11 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
bool callConditional(const int condition) {
|
2018-02-25 19:48:01 +00:00
|
|
|
MEMPTR() = fetchWord();
|
2017-06-11 20:08:40 +00:00
|
|
|
if (condition)
|
2018-03-18 22:40:23 +00:00
|
|
|
call(MEMPTR());
|
2018-08-17 12:59:59 +00:00
|
|
|
return !!condition;
|
2017-06-11 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2018-08-17 12:59:59 +00:00
|
|
|
bool jumpConditional(const int condition) {
|
2018-02-25 19:48:01 +00:00
|
|
|
MEMPTR() = fetchWord();
|
2018-08-17 12:59:59 +00:00
|
|
|
if (condition)
|
2018-03-18 22:40:23 +00:00
|
|
|
jump(MEMPTR());
|
2018-08-17 12:59:59 +00:00
|
|
|
return !!condition;
|
2017-06-11 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
bool returnConditional(const int condition) {
|
2018-08-17 12:59:59 +00:00
|
|
|
if (condition)
|
2017-06-11 20:08:40 +00:00
|
|
|
ret();
|
2018-08-17 12:59:59 +00:00
|
|
|
return !!condition;
|
2017-06-11 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2018-04-14 08:39:06 +00:00
|
|
|
void jr(const int8_t offset) {
|
2018-08-17 12:59:59 +00:00
|
|
|
jump(MEMPTR() = PC() + offset);
|
2017-06-11 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2018-08-17 12:59:59 +00:00
|
|
|
bool jrConditional(const int condition) {
|
2017-10-23 23:04:13 +00:00
|
|
|
const auto offset = fetchByte();
|
2018-08-17 12:59:59 +00:00
|
|
|
if (condition)
|
2017-06-11 20:08:40 +00:00
|
|
|
jr(offset);
|
2018-08-17 12:59:59 +00:00
|
|
|
return !!condition;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void ret() final {
|
|
|
|
Processor::ret();
|
|
|
|
MEMPTR() = PC();
|
2017-06-11 20:08:40 +00:00
|
|
|
}
|
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
private:
|
2017-07-21 12:33:17 +00:00
|
|
|
std::array<opcode_decoded_t, 0x100> m_decodedOpcodes;
|
2018-06-15 23:55:32 +00:00
|
|
|
register16_t m_sp = 0xffff;
|
|
|
|
register16_t m_memptr;
|
2017-06-11 08:45:34 +00:00
|
|
|
};
|
2017-11-30 23:19:17 +00:00
|
|
|
}
|