2017-06-04 20:38:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
2017-10-28 12:08:07 +00:00
|
|
|
#include <cassert>
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-09-01 15:41:50 +00:00
|
|
|
#include <IntelProcessor.h>
|
|
|
|
#include <Signal.h>
|
2017-10-19 21:43:09 +00:00
|
|
|
#include <Register.h>
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
namespace EightBit {
|
2017-09-07 00:15:28 +00:00
|
|
|
namespace GameBoy {
|
2017-10-19 21:43:09 +00:00
|
|
|
|
|
|
|
class Bus;
|
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
class LR35902 final : public IntelProcessor {
|
2017-09-07 00:15:28 +00:00
|
|
|
public:
|
|
|
|
enum StatusBits {
|
|
|
|
ZF = Bit7,
|
|
|
|
NF = Bit6,
|
|
|
|
HC = Bit5,
|
|
|
|
CF = Bit4,
|
|
|
|
};
|
|
|
|
|
|
|
|
LR35902(Bus& memory);
|
|
|
|
|
|
|
|
Signal<LR35902> ExecutingInstruction;
|
2017-09-23 21:56:11 +00:00
|
|
|
Signal<LR35902> ExecutedInstruction;
|
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] register16_t& AF() final;
|
|
|
|
[[nodiscard]] register16_t& BC() final;
|
|
|
|
[[nodiscard]] register16_t& DE() final;
|
|
|
|
[[nodiscard]] register16_t& HL() final;
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2020-11-12 16:22:44 +00:00
|
|
|
bool& IME() noexcept { return m_ime; }
|
|
|
|
|
|
|
|
[[nodiscard]] uint8_t enabledInterrupts();
|
|
|
|
[[nodiscard]] uint8_t flaggedInterrupts();
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] uint8_t maskedInterrupts();
|
2020-11-07 09:41:12 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
protected:
|
2018-12-29 19:17:36 +00:00
|
|
|
virtual int execute() final;
|
2017-12-10 21:41:48 +00:00
|
|
|
virtual int step() final;
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
void handleRESET() final;
|
|
|
|
void handleINT() final;
|
|
|
|
|
2020-11-12 18:21:51 +00:00
|
|
|
void memoryWrite() final {
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-12 18:21:51 +00:00
|
|
|
IntelProcessor::memoryWrite();
|
2020-11-09 11:48:59 +00:00
|
|
|
}
|
|
|
|
|
2020-11-12 18:21:51 +00:00
|
|
|
uint8_t memoryRead() final {
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-12 18:21:51 +00:00
|
|
|
return IntelProcessor::memoryRead();
|
|
|
|
}
|
|
|
|
|
|
|
|
void pushWord(register16_t value) final {
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-12 18:21:51 +00:00
|
|
|
IntelProcessor::pushWord(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void jr(int8_t offset) final {
|
|
|
|
IntelProcessor::jr(offset);
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-09 11:48:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int jumpConditional(const int condition) final {
|
2020-11-12 18:21:51 +00:00
|
|
|
if (IntelProcessor::jumpConditional(condition))
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-09 11:48:59 +00:00
|
|
|
return condition;
|
|
|
|
}
|
|
|
|
|
|
|
|
int returnConditional(const int condition) final {
|
2020-11-12 18:21:51 +00:00
|
|
|
IntelProcessor::returnConditional(condition);
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-09 11:48:59 +00:00
|
|
|
return condition;
|
|
|
|
}
|
|
|
|
|
|
|
|
int jrConditional(const int condition) final {
|
2020-11-12 18:21:51 +00:00
|
|
|
if (!IntelProcessor::jrConditional(condition))
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-09 11:48:59 +00:00
|
|
|
return condition;
|
|
|
|
}
|
2018-08-25 00:57:22 +00:00
|
|
|
|
2020-11-12 18:21:51 +00:00
|
|
|
void ret() final {
|
|
|
|
IntelProcessor::ret();
|
2020-11-13 10:14:06 +00:00
|
|
|
tick(4);
|
2020-11-12 18:21:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
private:
|
|
|
|
Bus& m_bus;
|
|
|
|
|
2018-06-15 23:55:32 +00:00
|
|
|
register16_t af = 0xffff;
|
|
|
|
register16_t bc = 0xffff;
|
|
|
|
register16_t de = 0xffff;
|
|
|
|
register16_t hl = 0xffff;
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2017-11-11 11:12:09 +00:00
|
|
|
bool m_ime = false;
|
|
|
|
bool m_stopped = false;
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2017-11-11 11:12:09 +00:00
|
|
|
bool m_prefixCB = false;
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] auto R(const int r) {
|
2018-06-23 15:43:05 +00:00
|
|
|
ASSUME(r >= 0);
|
|
|
|
ASSUME(r <= 7);
|
2017-09-07 00:15:28 +00:00
|
|
|
switch (r) {
|
|
|
|
case 0:
|
|
|
|
return B();
|
|
|
|
case 1:
|
|
|
|
return C();
|
|
|
|
case 2:
|
|
|
|
return D();
|
|
|
|
case 3:
|
|
|
|
return E();
|
|
|
|
case 4:
|
|
|
|
return H();
|
|
|
|
case 5:
|
|
|
|
return L();
|
|
|
|
case 6:
|
2020-02-09 11:51:58 +00:00
|
|
|
return IntelProcessor::memoryRead(HL());
|
2017-09-07 00:15:28 +00:00
|
|
|
case 7:
|
2018-06-23 15:43:05 +00:00
|
|
|
return A();
|
2017-12-10 21:41:48 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE;
|
2017-09-07 00:15:28 +00:00
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2018-06-23 15:43:05 +00:00
|
|
|
void R(const int r, const uint8_t value) {
|
|
|
|
ASSUME(r >= 0);
|
|
|
|
ASSUME(r <= 7);
|
2017-09-07 00:15:28 +00:00
|
|
|
switch (r) {
|
|
|
|
case 0:
|
|
|
|
B() = value;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
C() = value;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
D() = value;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
E() = value;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
H() = value;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
L() = value;
|
|
|
|
break;
|
|
|
|
case 6:
|
2020-02-09 11:51:58 +00:00
|
|
|
IntelProcessor::memoryWrite(HL(), value);
|
2017-09-07 00:15:28 +00:00
|
|
|
break;
|
|
|
|
case 7:
|
2018-06-23 15:43:05 +00:00
|
|
|
A() = value;
|
2017-09-07 00:15:28 +00:00
|
|
|
break;
|
2017-12-10 21:41:48 +00:00
|
|
|
default:
|
|
|
|
UNREACHABLE;
|
2017-09-07 00:15:28 +00:00
|
|
|
}
|
2017-08-06 16:06:48 +00:00
|
|
|
}
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] auto& RP(const int rp) {
|
2018-06-23 15:43:05 +00:00
|
|
|
ASSUME(rp >= 0);
|
|
|
|
ASSUME(rp <= 3);
|
2017-09-07 00:15:28 +00:00
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return SP();
|
|
|
|
default:
|
2017-10-02 15:47:05 +00:00
|
|
|
UNREACHABLE;
|
2017-09-07 00:15:28 +00:00
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-09-07 00:15:28 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] auto& RP2(const int rp) {
|
2018-06-23 15:43:05 +00:00
|
|
|
ASSUME(rp >= 0);
|
|
|
|
ASSUME(rp <= 3);
|
2017-09-07 00:15:28 +00:00
|
|
|
switch (rp) {
|
|
|
|
case 0b00:
|
|
|
|
return BC();
|
|
|
|
case 0b01:
|
|
|
|
return DE();
|
|
|
|
case 0b10:
|
|
|
|
return HL();
|
|
|
|
case 0b11:
|
|
|
|
return AF();
|
|
|
|
default:
|
2017-10-02 15:47:05 +00:00
|
|
|
UNREACHABLE;
|
2017-09-07 00:15:28 +00:00
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] static auto adjustHalfCarryAdd(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
|
|
|
|
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
2017-09-07 00:15:28 +00:00
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] static auto adjustHalfCarrySub(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
|
|
|
|
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
|
2017-09-07 00:15:28 +00:00
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] static bool convertCondition(uint8_t f, int flag);
|
|
|
|
|
|
|
|
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2018-06-23 15:43:05 +00:00
|
|
|
void executeCB(int x, int y, int z, int p, int q);
|
|
|
|
void executeOther(int x, int y, int z, int p, int q);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand);
|
|
|
|
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2020-11-07 09:41:12 +00:00
|
|
|
void stop(bool value = true) noexcept { m_stopped = value; }
|
|
|
|
void start() noexcept { stop(false); }
|
|
|
|
bool stopped() const noexcept { return m_stopped; }
|
2017-08-30 22:17:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
void di();
|
|
|
|
void ei();
|
2017-08-30 22:17:34 +00:00
|
|
|
|
2017-09-07 00:15:28 +00:00
|
|
|
void reti();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
void jrConditionalFlag(uint8_t f, int flag);
|
|
|
|
void returnConditionalFlag(uint8_t f, int flag);
|
|
|
|
void jumpConditionalFlag(uint8_t f, int flag);
|
|
|
|
void callConditionalFlag(uint8_t f, int flag);
|
2018-06-23 15:43:05 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value);
|
2018-06-23 15:43:05 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[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);
|
2020-11-12 18:21:51 +00:00
|
|
|
static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value);
|
2020-11-09 11:48:59 +00:00
|
|
|
[[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);
|
2018-06-23 15:43:05 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[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);
|
2018-06-23 15:43:05 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
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);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
static void scf(uint8_t& f, uint8_t operand);
|
|
|
|
static void ccf(uint8_t& f, uint8_t operand);
|
|
|
|
static uint8_t cpl(uint8_t& f, uint8_t operand);
|
2017-07-19 12:59:28 +00:00
|
|
|
|
2020-11-09 11:48:59 +00:00
|
|
|
static uint8_t swap(uint8_t& f, uint8_t operand);
|
2017-09-07 00:15:28 +00:00
|
|
|
};
|
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|