2017-06-04 20:38:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
2017-06-11 08:45:34 +00:00
|
|
|
#include "IntelProcessor.h"
|
2017-06-09 09:23:51 +00:00
|
|
|
#include "Bus.h"
|
2017-06-11 08:45:34 +00:00
|
|
|
#include "Signal.h"
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
namespace EightBit {
|
2017-06-11 08:45:34 +00:00
|
|
|
class LR35902 : public IntelProcessor {
|
2017-06-09 10:42:32 +00:00
|
|
|
public:
|
|
|
|
enum StatusBits {
|
|
|
|
ZF = Bit7,
|
|
|
|
NF = Bit6,
|
|
|
|
HC = Bit5,
|
|
|
|
CF = Bit4,
|
|
|
|
};
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
LR35902(Bus& memory);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
Signal<LR35902> ExecutingInstruction;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void stop() { m_stopped = true; }
|
|
|
|
void start() { m_stopped = false; }
|
|
|
|
bool stopped() const { return m_stopped; }
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
bool& IME() { return m_ime; }
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void di();
|
|
|
|
void ei();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
int interrupt(uint8_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
int execute(uint8_t opcode);
|
|
|
|
int step();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
// Mutable access to processor!!
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-16 12:52:10 +00:00
|
|
|
virtual register16_t& AF() override {
|
2017-06-09 10:42:32 +00:00
|
|
|
m_accumulatorFlag.low &= 0xf0;
|
|
|
|
return m_accumulatorFlag;
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-16 12:52:10 +00:00
|
|
|
virtual register16_t& BC() override {
|
2017-06-09 10:42:32 +00:00
|
|
|
return m_registers[BC_IDX];
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-16 12:52:10 +00:00
|
|
|
virtual register16_t& DE() override {
|
2017-06-09 10:42:32 +00:00
|
|
|
return m_registers[DE_IDX];
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-16 12:52:10 +00:00
|
|
|
virtual register16_t& HL() override {
|
2017-06-09 10:42:32 +00:00
|
|
|
return m_registers[HL_IDX];
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
virtual void reset();
|
|
|
|
virtual void initialise();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
private:
|
|
|
|
enum { BC_IDX, DE_IDX, HL_IDX };
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
std::array<register16_t, 3> m_registers;
|
|
|
|
register16_t m_accumulatorFlag;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
bool m_ime;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
bool m_prefixCB;
|
2017-06-09 09:23:51 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
bool m_stopped;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
int fetchExecute() {
|
|
|
|
return execute(fetchByte());
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
uint8_t& R(int r) {
|
|
|
|
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:
|
|
|
|
m_memory.ADDRESS() = HL();
|
|
|
|
return m_memory.reference();
|
|
|
|
case 7:
|
|
|
|
return A();
|
|
|
|
}
|
|
|
|
throw std::logic_error("Unhandled registry mechanism");
|
2017-06-04 20:38:34 +00:00
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
|
|
|
|
register16_t& RP(int rp) {
|
|
|
|
switch (rp) {
|
|
|
|
case 3:
|
2017-06-19 12:53:00 +00:00
|
|
|
return SP();
|
2017-06-09 10:42:32 +00:00
|
|
|
default:
|
|
|
|
return m_registers[rp];
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
}
|
2017-06-09 10:42:32 +00:00
|
|
|
|
|
|
|
register16_t& RP2(int rp) {
|
|
|
|
switch (rp) {
|
|
|
|
case 3:
|
|
|
|
return AF();
|
|
|
|
default:
|
|
|
|
return m_registers[rp];
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
}
|
|
|
|
|
2017-06-19 12:53:00 +00:00
|
|
|
static void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
2017-06-18 17:14:39 +00:00
|
|
|
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-19 12:53:00 +00:00
|
|
|
static void adjustHalfCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
2017-06-18 17:14:39 +00:00
|
|
|
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
|
2017-06-09 10:42:32 +00:00
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +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
|
|
|
|
2017-06-19 12:53:00 +00:00
|
|
|
static void adjustZero(uint8_t& f, uint8_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-19 12:53:00 +00:00
|
|
|
static void postIncrement(uint8_t& f, uint8_t value);
|
|
|
|
static void postDecrement(uint8_t& f, uint8_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void reti();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-11 20:08:40 +00:00
|
|
|
bool jrConditionalFlag(int flag);
|
|
|
|
bool returnConditionalFlag(int flag);
|
|
|
|
bool jumpConditionalFlag(int flag);
|
|
|
|
bool callConditionalFlag(int flag);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 15:01:12 +00:00
|
|
|
void sbc(register16_t& operand, register16_t value);
|
|
|
|
void adc(register16_t& operand, register16_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 15:01:12 +00:00
|
|
|
void add(register16_t& operand, register16_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 15:01:12 +00:00
|
|
|
void add(uint8_t& operand, uint8_t value, int carry = 0);
|
2017-06-09 10:42:32 +00:00
|
|
|
void adc(uint8_t& operand, uint8_t value);
|
2017-06-09 15:01:12 +00:00
|
|
|
void sub(uint8_t& operand, uint8_t value, int carry = 0);
|
|
|
|
void sbc(uint8_t& operand, uint8_t value);
|
2017-06-09 10:42:32 +00:00
|
|
|
void andr(uint8_t& operand, uint8_t value);
|
2017-06-09 15:01:12 +00:00
|
|
|
void xorr(uint8_t& operand, uint8_t value);
|
|
|
|
void orr(uint8_t& operand, uint8_t value);
|
2017-06-09 10:42:32 +00:00
|
|
|
void compare(uint8_t value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void rlc(uint8_t& operand);
|
|
|
|
void rrc(uint8_t& operand);
|
|
|
|
void rl(uint8_t& operand);
|
|
|
|
void rr(uint8_t& operand);
|
|
|
|
void sla(uint8_t& operand);
|
|
|
|
void sra(uint8_t& operand);
|
|
|
|
void srl(uint8_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void bit(int n, uint8_t& operand);
|
|
|
|
void res(int n, uint8_t& operand);
|
|
|
|
void set(int nit, uint8_t& operand);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void daa();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void scf();
|
|
|
|
void ccf();
|
|
|
|
void cpl();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-06-09 10:42:32 +00:00
|
|
|
void swap(uint8_t& operand);
|
|
|
|
};
|
|
|
|
}
|