mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-22 09:30:32 +00:00
Bring LR35902 a little more in line with the Z80 implementation.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
1c8d842bde
commit
93bac42547
@ -2,105 +2,107 @@
|
||||
|
||||
#include "Memory.h"
|
||||
|
||||
class Bus : public EightBit::Memory {
|
||||
public:
|
||||
namespace EightBit {
|
||||
class Bus : public Memory {
|
||||
public:
|
||||
|
||||
enum {
|
||||
TotalLineCount = 154
|
||||
enum {
|
||||
TotalLineCount = 154
|
||||
};
|
||||
|
||||
enum {
|
||||
VideoRam = 0x8000
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
BASE = 0xFF00,
|
||||
|
||||
// Port/Mode Registers
|
||||
P1 = 0x0,
|
||||
SB = 0x1,
|
||||
SC = 0x2,
|
||||
DIV = 0x4,
|
||||
TIMA = 0x5,
|
||||
TMA = 0x6,
|
||||
TAC = 0x7,
|
||||
|
||||
// Interrupt Flags
|
||||
IF = 0xF,
|
||||
IE = 0xFF,
|
||||
|
||||
// LCD Display Registers
|
||||
LCDC = 0x40,
|
||||
STAT = 0x41,
|
||||
SCY = 0x42,
|
||||
SCX = 0x43,
|
||||
LY = 0x44,
|
||||
LYC = 0x45,
|
||||
DMA = 0x46,
|
||||
BGP = 0x47,
|
||||
OBP0 = 0x48,
|
||||
OBP1 = 0x49,
|
||||
WY = 0x4A,
|
||||
WX = 0x4B,
|
||||
|
||||
// Sound Registers
|
||||
NR10 = 0x10,
|
||||
NR11 = 0x11,
|
||||
NR12 = 0x12,
|
||||
NR13 = 0x13,
|
||||
NR14 = 0x14,
|
||||
NR21 = 0x16,
|
||||
NR22 = 0x17,
|
||||
NR23 = 0x18,
|
||||
NR24 = 0x19,
|
||||
NR30 = 0x1A,
|
||||
NR31 = 0x1B,
|
||||
NR32 = 0x1C,
|
||||
NR33 = 0x1D,
|
||||
NR34 = 0x1E,
|
||||
NR41 = 0x20,
|
||||
NR42 = 0x21,
|
||||
NR43 = 0x22,
|
||||
NR44 = 0x23,
|
||||
NR50 = 0x24,
|
||||
NR51 = 0x25,
|
||||
NR52 = 0x26,
|
||||
|
||||
WPRAM_START = 0x30,
|
||||
WPRAM_END = 0x3F,
|
||||
|
||||
// Boot rom control
|
||||
BOOT_DISABLE = 0x50,
|
||||
};
|
||||
|
||||
Bus();
|
||||
|
||||
void reset();
|
||||
|
||||
uint8_t& REG(int offset) {
|
||||
ADDRESS().word = BASE + offset;
|
||||
return Memory::reference();
|
||||
}
|
||||
|
||||
void incrementLY() {
|
||||
REG(LY) = (REG(LY) + 1) % TotalLineCount;
|
||||
}
|
||||
|
||||
void resetLY() {
|
||||
REG(LY) = 0;
|
||||
}
|
||||
|
||||
void loadBootRom(const std::string& path);
|
||||
|
||||
bool isBootRom(uint16_t address) const {
|
||||
return (address < m_boot.size()) && (peek(BASE + BOOT_DISABLE) == 0);
|
||||
}
|
||||
|
||||
virtual uint8_t peek(uint16_t address) const;
|
||||
|
||||
virtual uint8_t& reference();
|
||||
|
||||
private:
|
||||
std::array<uint8_t, 0x100> m_boot;
|
||||
};
|
||||
|
||||
enum {
|
||||
VideoRam = 0x8000
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
BASE = 0xFF00,
|
||||
|
||||
// Port/Mode Registers
|
||||
P1 = 0x0,
|
||||
SB = 0x1,
|
||||
SC = 0x2,
|
||||
DIV = 0x4,
|
||||
TIMA = 0x5,
|
||||
TMA = 0x6,
|
||||
TAC = 0x7,
|
||||
|
||||
// Interrupt Flags
|
||||
IF = 0xF,
|
||||
IE = 0xFF,
|
||||
|
||||
// LCD Display Registers
|
||||
LCDC = 0x40,
|
||||
STAT = 0x41,
|
||||
SCY = 0x42,
|
||||
SCX = 0x43,
|
||||
LY = 0x44,
|
||||
LYC = 0x45,
|
||||
DMA = 0x46,
|
||||
BGP = 0x47,
|
||||
OBP0 = 0x48,
|
||||
OBP1 = 0x49,
|
||||
WY = 0x4A,
|
||||
WX = 0x4B,
|
||||
|
||||
// Sound Registers
|
||||
NR10 = 0x10,
|
||||
NR11 = 0x11,
|
||||
NR12 = 0x12,
|
||||
NR13 = 0x13,
|
||||
NR14 = 0x14,
|
||||
NR21 = 0x16,
|
||||
NR22 = 0x17,
|
||||
NR23 = 0x18,
|
||||
NR24 = 0x19,
|
||||
NR30 = 0x1A,
|
||||
NR31 = 0x1B,
|
||||
NR32 = 0x1C,
|
||||
NR33 = 0x1D,
|
||||
NR34 = 0x1E,
|
||||
NR41 = 0x20,
|
||||
NR42 = 0x21,
|
||||
NR43 = 0x22,
|
||||
NR44 = 0x23,
|
||||
NR50 = 0x24,
|
||||
NR51 = 0x25,
|
||||
NR52 = 0x26,
|
||||
|
||||
WPRAM_START = 0x30,
|
||||
WPRAM_END = 0x3F,
|
||||
|
||||
// Boot rom control
|
||||
BOOT_DISABLE = 0x50,
|
||||
};
|
||||
|
||||
Bus();
|
||||
|
||||
void reset();
|
||||
|
||||
uint8_t& REG(int offset) {
|
||||
ADDRESS().word = BASE + offset;
|
||||
return Memory::reference();
|
||||
}
|
||||
|
||||
void incrementLY() {
|
||||
REG(LY) = (REG(LY) + 1) % TotalLineCount;
|
||||
}
|
||||
|
||||
void resetLY() {
|
||||
REG(LY) = 0;
|
||||
}
|
||||
|
||||
void loadBootRom(const std::string& path);
|
||||
|
||||
bool isBootRom(uint16_t address) const {
|
||||
return (address < m_boot.size()) && (peek(BASE + BOOT_DISABLE) == 0);
|
||||
}
|
||||
|
||||
virtual uint8_t peek(uint16_t address) const;
|
||||
|
||||
virtual uint8_t& reference();
|
||||
|
||||
private:
|
||||
std::array<uint8_t, 0x100> m_boot;
|
||||
};
|
||||
}
|
@ -3,51 +3,54 @@
|
||||
#include <string>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
class LR35902;
|
||||
namespace EightBit {
|
||||
|
||||
class Disassembler {
|
||||
public:
|
||||
Disassembler();
|
||||
class LR35902;
|
||||
|
||||
static std::string state(LR35902& cpu);
|
||||
std::string disassemble(LR35902& cpu);
|
||||
class Disassembler {
|
||||
public:
|
||||
Disassembler();
|
||||
|
||||
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
||||
static std::string flags(uint8_t value);
|
||||
static std::string hex(uint8_t value);
|
||||
static std::string hex(uint16_t value);
|
||||
static std::string binary(uint8_t value);
|
||||
static std::string decimal(uint8_t value);
|
||||
static std::string state(LR35902& cpu);
|
||||
std::string disassemble(LR35902& cpu);
|
||||
|
||||
static std::string invalid(uint8_t value);
|
||||
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
||||
static std::string flags(uint8_t value);
|
||||
static std::string hex(uint8_t value);
|
||||
static std::string hex(uint16_t value);
|
||||
static std::string binary(uint8_t value);
|
||||
static std::string decimal(uint8_t value);
|
||||
|
||||
private:
|
||||
mutable boost::format m_formatter;
|
||||
bool m_prefixCB;
|
||||
static std::string invalid(uint8_t value);
|
||||
|
||||
void disassemble(std::ostringstream& output, LR35902& cpu, uint16_t pc);
|
||||
private:
|
||||
mutable boost::format m_formatter;
|
||||
bool m_prefixCB;
|
||||
|
||||
void disassembleCB(
|
||||
std::ostringstream& output,
|
||||
LR35902& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
void disassemble(std::ostringstream& output, LR35902& cpu, uint16_t pc);
|
||||
|
||||
void disassembleOther(
|
||||
std::ostringstream& output,
|
||||
LR35902& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
void disassembleCB(
|
||||
std::ostringstream& output,
|
||||
LR35902& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
|
||||
std::string RP(int rp) const;
|
||||
std::string RP2(int rp) const;
|
||||
std::string R(int r) const;
|
||||
static std::string cc(int flag);
|
||||
static std::string alu(int which);
|
||||
};
|
||||
void disassembleOther(
|
||||
std::ostringstream& output,
|
||||
LR35902& cpu,
|
||||
uint16_t pc,
|
||||
std::string& specification,
|
||||
int& dumpCount,
|
||||
int x, int y, int z,
|
||||
int p, int q);
|
||||
|
||||
std::string RP(int rp) const;
|
||||
std::string RP2(int rp) const;
|
||||
std::string R(int r) const;
|
||||
static std::string cc(int flag);
|
||||
static std::string alu(int which);
|
||||
};
|
||||
}
|
@ -5,226 +5,228 @@
|
||||
#include "Processor.h"
|
||||
#include "Bus.h"
|
||||
|
||||
class LR35902 : public EightBit::Processor {
|
||||
public:
|
||||
enum StatusBits {
|
||||
ZF = Bit7,
|
||||
NF = Bit6,
|
||||
HC = Bit5,
|
||||
CF = Bit4,
|
||||
namespace EightBit {
|
||||
class LR35902 : public Processor {
|
||||
public:
|
||||
enum StatusBits {
|
||||
ZF = Bit7,
|
||||
NF = Bit6,
|
||||
HC = Bit5,
|
||||
CF = Bit4,
|
||||
};
|
||||
|
||||
LR35902(Bus& memory);
|
||||
|
||||
Signal<LR35902> ExecutingInstruction;
|
||||
|
||||
void stop() { m_stopped = true; }
|
||||
void start() { m_stopped = false; }
|
||||
bool stopped() const { return m_stopped; }
|
||||
|
||||
bool& IME() { return m_ime; }
|
||||
|
||||
void di();
|
||||
void ei();
|
||||
|
||||
int interrupt(uint8_t value);
|
||||
|
||||
int execute(uint8_t opcode);
|
||||
int step();
|
||||
|
||||
// Mutable access to processor!!
|
||||
|
||||
register16_t& AF() {
|
||||
m_accumulatorFlag.low &= 0xf0;
|
||||
return m_accumulatorFlag;
|
||||
}
|
||||
|
||||
uint8_t& A() { return AF().high; }
|
||||
uint8_t& F() { return AF().low; }
|
||||
|
||||
register16_t& BC() {
|
||||
return m_registers[BC_IDX];
|
||||
}
|
||||
|
||||
uint8_t& B() { return BC().high; }
|
||||
uint8_t& C() { return BC().low; }
|
||||
|
||||
register16_t& DE() {
|
||||
return m_registers[DE_IDX];
|
||||
}
|
||||
|
||||
uint8_t& D() { return DE().high; }
|
||||
uint8_t& E() { return DE().low; }
|
||||
|
||||
register16_t& HL() {
|
||||
return m_registers[HL_IDX];
|
||||
}
|
||||
|
||||
uint8_t& H() { return HL().high; }
|
||||
uint8_t& L() { return HL().low; }
|
||||
|
||||
virtual void reset();
|
||||
virtual void initialise();
|
||||
|
||||
private:
|
||||
enum { BC_IDX, DE_IDX, HL_IDX };
|
||||
|
||||
std::array<register16_t, 3> m_registers;
|
||||
register16_t m_accumulatorFlag;
|
||||
|
||||
bool m_ime;
|
||||
|
||||
bool m_prefixCB;
|
||||
|
||||
bool m_stopped;
|
||||
|
||||
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
|
||||
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
|
||||
|
||||
register16_t fetchWord() {
|
||||
register16_t returned;
|
||||
Processor::fetchWord(returned);
|
||||
return returned;
|
||||
}
|
||||
|
||||
int fetchExecute() {
|
||||
return execute(fetchByte());
|
||||
}
|
||||
|
||||
void clearFlag(int flag) { F() &= ~flag; }
|
||||
void setFlag(int flag) { F() |= flag; }
|
||||
|
||||
void setFlag(int flag, int condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, uint32_t condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, bool condition) { condition ? setFlag(flag) : clearFlag(flag); }
|
||||
|
||||
void clearFlag(int flag, int condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, uint32_t condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, bool condition) { condition ? clearFlag(flag) : setFlag(flag); }
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
register16_t& RP(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return sp;
|
||||
default:
|
||||
return m_registers[rp];
|
||||
}
|
||||
}
|
||||
|
||||
register16_t& RP2(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return AF();
|
||||
default:
|
||||
return m_registers[rp];
|
||||
}
|
||||
}
|
||||
|
||||
int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) {
|
||||
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
}
|
||||
|
||||
void adjustHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableAdd[index & 0x7]);
|
||||
}
|
||||
|
||||
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
|
||||
}
|
||||
|
||||
void executeCB(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
|
||||
void adjustZero(uint8_t value);
|
||||
|
||||
void postIncrement(uint8_t value);
|
||||
void postDecrement(uint8_t value);
|
||||
|
||||
void restart(uint8_t address);
|
||||
|
||||
void jrConditional(int conditional);
|
||||
void jrConditionalFlag(int flag);
|
||||
|
||||
void ret();
|
||||
void reti();
|
||||
|
||||
void returnConditional(int condition);
|
||||
void returnConditionalFlag(int flag);
|
||||
|
||||
void jumpConditional(int condition);
|
||||
void jumpConditionalFlag(int flag);
|
||||
|
||||
void call(uint16_t address);
|
||||
void callConditional(uint16_t address, int condition);
|
||||
void callConditionalFlag(uint16_t address, int flag);
|
||||
|
||||
uint16_t sbc(uint16_t value);
|
||||
uint16_t adc(uint16_t value);
|
||||
|
||||
uint16_t add(uint16_t value);
|
||||
|
||||
void sub(uint8_t& operand, uint8_t value, bool carry);
|
||||
void sub(uint8_t& operand, uint8_t value);
|
||||
void sbc(uint8_t& operand, uint8_t value);
|
||||
|
||||
void add(uint8_t& operand, uint8_t value, bool carry);
|
||||
void add(uint8_t& operand, uint8_t value);
|
||||
void adc(uint8_t& operand, uint8_t value);
|
||||
|
||||
void andr(uint8_t& operand, uint8_t value);
|
||||
|
||||
void anda(uint8_t value);
|
||||
void xora(uint8_t value);
|
||||
void ora(uint8_t value);
|
||||
void compare(uint8_t value);
|
||||
|
||||
void rlca();
|
||||
void rrca();
|
||||
void rla();
|
||||
void rra();
|
||||
|
||||
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);
|
||||
|
||||
void bit(int n, uint8_t& operand);
|
||||
void res(int n, uint8_t& operand);
|
||||
void set(int nit, uint8_t& operand);
|
||||
|
||||
void daa();
|
||||
|
||||
void scf();
|
||||
void ccf();
|
||||
void cpl();
|
||||
|
||||
void swap(uint8_t& operand);
|
||||
};
|
||||
|
||||
LR35902(Bus& memory);
|
||||
|
||||
EightBit::Signal<LR35902> ExecutingInstruction;
|
||||
|
||||
void stop() { m_stopped = true; }
|
||||
void start() { m_stopped = false; }
|
||||
bool stopped() const { return m_stopped; }
|
||||
|
||||
bool& IME() { return m_ime; }
|
||||
|
||||
void di();
|
||||
void ei();
|
||||
|
||||
int interrupt(uint8_t value);
|
||||
|
||||
int execute(uint8_t opcode);
|
||||
int step();
|
||||
|
||||
// Mutable access to processor!!
|
||||
|
||||
EightBit::register16_t& AF() {
|
||||
m_accumulatorFlag.low &= 0xf0;
|
||||
return m_accumulatorFlag;
|
||||
}
|
||||
|
||||
uint8_t& A() { return AF().high; }
|
||||
uint8_t& F() { return AF().low; }
|
||||
|
||||
EightBit::register16_t& BC() {
|
||||
return m_registers[BC_IDX];
|
||||
}
|
||||
|
||||
uint8_t& B() { return BC().high; }
|
||||
uint8_t& C() { return BC().low; }
|
||||
|
||||
EightBit::register16_t& DE() {
|
||||
return m_registers[DE_IDX];
|
||||
}
|
||||
|
||||
uint8_t& D() { return DE().high; }
|
||||
uint8_t& E() { return DE().low; }
|
||||
|
||||
EightBit::register16_t& HL() {
|
||||
return m_registers[HL_IDX];
|
||||
}
|
||||
|
||||
uint8_t& H() { return HL().high; }
|
||||
uint8_t& L() { return HL().low; }
|
||||
|
||||
virtual void reset();
|
||||
virtual void initialise();
|
||||
|
||||
private:
|
||||
enum { BC_IDX, DE_IDX, HL_IDX };
|
||||
|
||||
std::array<EightBit::register16_t, 3> m_registers;
|
||||
EightBit::register16_t m_accumulatorFlag;
|
||||
|
||||
bool m_ime;
|
||||
|
||||
bool m_prefixCB;
|
||||
|
||||
bool m_stopped;
|
||||
|
||||
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
|
||||
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
|
||||
|
||||
EightBit::register16_t fetchWord() {
|
||||
EightBit::register16_t returned;
|
||||
Processor::fetchWord(returned);
|
||||
return returned;
|
||||
}
|
||||
|
||||
int fetchExecute() {
|
||||
return execute(fetchByte());
|
||||
}
|
||||
|
||||
void clearFlag(int flag) { F() &= ~flag; }
|
||||
void setFlag(int flag) { F() |= flag; }
|
||||
|
||||
void setFlag(int flag, int condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, uint32_t condition) { setFlag(flag, condition != 0); }
|
||||
void setFlag(int flag, bool condition) { condition ? setFlag(flag) : clearFlag(flag); }
|
||||
|
||||
void clearFlag(int flag, int condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, uint32_t condition) { clearFlag(flag, condition != 0); }
|
||||
void clearFlag(int flag, bool condition) { condition ? clearFlag(flag) : setFlag(flag); }
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
EightBit::register16_t& RP(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return sp;
|
||||
default:
|
||||
return m_registers[rp];
|
||||
}
|
||||
}
|
||||
|
||||
EightBit::register16_t& RP2(int rp) {
|
||||
switch (rp) {
|
||||
case 3:
|
||||
return AF();
|
||||
default:
|
||||
return m_registers[rp];
|
||||
}
|
||||
}
|
||||
|
||||
int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) {
|
||||
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
}
|
||||
|
||||
void adjustHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableAdd[index & 0x7]);
|
||||
}
|
||||
|
||||
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
|
||||
}
|
||||
|
||||
void executeCB(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
|
||||
void adjustZero(uint8_t value);
|
||||
|
||||
void postIncrement(uint8_t value);
|
||||
void postDecrement(uint8_t value);
|
||||
|
||||
void restart(uint8_t address);
|
||||
|
||||
void jrConditional(int conditional);
|
||||
void jrConditionalFlag(int flag);
|
||||
|
||||
void ret();
|
||||
void reti();
|
||||
|
||||
void returnConditional(int condition);
|
||||
void returnConditionalFlag(int flag);
|
||||
|
||||
void jumpConditional(int condition);
|
||||
void jumpConditionalFlag(int flag);
|
||||
|
||||
void call(uint16_t address);
|
||||
void callConditional(uint16_t address, int condition);
|
||||
void callConditionalFlag(uint16_t address, int flag);
|
||||
|
||||
uint16_t sbc(uint16_t value);
|
||||
uint16_t adc(uint16_t value);
|
||||
|
||||
uint16_t add(uint16_t value);
|
||||
|
||||
void sub(uint8_t& operand, uint8_t value, bool carry);
|
||||
void sub(uint8_t& operand, uint8_t value);
|
||||
void sbc(uint8_t& operand, uint8_t value);
|
||||
|
||||
void add(uint8_t& operand, uint8_t value, bool carry);
|
||||
void add(uint8_t& operand, uint8_t value);
|
||||
void adc(uint8_t& operand, uint8_t value);
|
||||
|
||||
void andr(uint8_t& operand, uint8_t value);
|
||||
|
||||
void anda(uint8_t value);
|
||||
void xora(uint8_t value);
|
||||
void ora(uint8_t value);
|
||||
void compare(uint8_t value);
|
||||
|
||||
void rlca();
|
||||
void rrca();
|
||||
void rla();
|
||||
void rra();
|
||||
|
||||
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);
|
||||
|
||||
void bit(int n, uint8_t& operand);
|
||||
void res(int n, uint8_t& operand);
|
||||
void set(int nit, uint8_t& operand);
|
||||
|
||||
void daa();
|
||||
|
||||
void scf();
|
||||
void ccf();
|
||||
void cpl();
|
||||
|
||||
void swap(uint8_t& operand);
|
||||
};
|
||||
}
|
@ -5,24 +5,26 @@
|
||||
|
||||
#include "Disassembler.h"
|
||||
|
||||
class LR35902;
|
||||
namespace EightBit {
|
||||
|
||||
class Profiler {
|
||||
public:
|
||||
Profiler(LR35902& cpu);
|
||||
class LR35902;
|
||||
|
||||
void add(uint16_t address, uint8_t instruction);
|
||||
class Profiler {
|
||||
public:
|
||||
Profiler(LR35902& cpu);
|
||||
|
||||
void dump() const;
|
||||
void add(uint16_t address, uint8_t instruction);
|
||||
|
||||
private:
|
||||
std::array<uint64_t, 0x100> m_instructions;
|
||||
std::array<uint64_t, 0x10000> m_addresses;
|
||||
LR35902& m_cpu;
|
||||
void dump() const;
|
||||
|
||||
Disassembler m_disassembler;
|
||||
private:
|
||||
std::array<uint64_t, 0x100> m_instructions;
|
||||
std::array<uint64_t, 0x10000> m_addresses;
|
||||
LR35902& m_cpu;
|
||||
|
||||
void dumpInstructionProfiles() const;
|
||||
void dumpAddressProfiles() const;
|
||||
};
|
||||
Disassembler m_disassembler;
|
||||
|
||||
void dumpInstructionProfiles() const;
|
||||
void dumpAddressProfiles() const;
|
||||
};
|
||||
}
|
@ -1,30 +1,30 @@
|
||||
#include "stdafx.h"
|
||||
#include "Bus.h"
|
||||
|
||||
Bus::Bus()
|
||||
EightBit::Bus::Bus()
|
||||
: Memory(0xffff) {
|
||||
}
|
||||
|
||||
void Bus::reset() {
|
||||
void EightBit::Bus::reset() {
|
||||
REG(NR52) = 0xf1;
|
||||
REG(LCDC) = 0x91;
|
||||
}
|
||||
|
||||
void Bus::loadBootRom(const std::string& path) {
|
||||
void EightBit::Bus::loadBootRom(const std::string& path) {
|
||||
auto size = loadMemory(path, 0);
|
||||
if (size != 0x100)
|
||||
throw std::runtime_error("Incorrectly sized boot ROM");
|
||||
std::copy_n(m_bus.cbegin(), size, m_boot.begin());
|
||||
}
|
||||
|
||||
uint8_t& Bus::reference() {
|
||||
uint8_t& EightBit::Bus::reference() {
|
||||
auto effective = effectiveAddress(ADDRESS().word);
|
||||
if (isBootRom(effective))
|
||||
return placeDATA(m_boot[effective]);
|
||||
return Memory::reference();
|
||||
}
|
||||
|
||||
uint8_t Bus::peek(uint16_t address) const {
|
||||
uint8_t EightBit::Bus::peek(uint16_t address) const {
|
||||
auto effective = effectiveAddress(address);
|
||||
if (isBootRom(effective))
|
||||
return m_boot[effective];
|
||||
|
@ -9,12 +9,12 @@
|
||||
#include "LR35902.h"
|
||||
#include "StatusFlags.h"
|
||||
|
||||
Disassembler::Disassembler() {
|
||||
EightBit::Disassembler::Disassembler() {
|
||||
// Disable exceptions where too many format arguments are available
|
||||
m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
|
||||
}
|
||||
|
||||
std::string Disassembler::state(LR35902& cpu) {
|
||||
std::string EightBit::Disassembler::state(EightBit::LR35902& cpu) {
|
||||
|
||||
auto pc = cpu.getProgramCounter();
|
||||
auto sp = cpu.getStackPointer();
|
||||
@ -45,7 +45,7 @@ std::string Disassembler::state(LR35902& cpu) {
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::RP(int rp) const {
|
||||
std::string EightBit::Disassembler::RP(int rp) const {
|
||||
switch (rp) {
|
||||
case 0:
|
||||
return "BC";
|
||||
@ -59,7 +59,7 @@ std::string Disassembler::RP(int rp) const {
|
||||
throw std::logic_error("Unhandled register pair");
|
||||
}
|
||||
|
||||
std::string Disassembler::RP2(int rp) const {
|
||||
std::string EightBit::Disassembler::RP2(int rp) const {
|
||||
switch (rp) {
|
||||
case 0:
|
||||
return "BC";
|
||||
@ -73,7 +73,7 @@ std::string Disassembler::RP2(int rp) const {
|
||||
throw std::logic_error("Unhandled register pair");
|
||||
}
|
||||
|
||||
std::string Disassembler::R(int r) const {
|
||||
std::string EightBit::Disassembler::R(int r) const {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return "B";
|
||||
@ -95,7 +95,7 @@ std::string Disassembler::R(int r) const {
|
||||
throw std::logic_error("Unhandled register");
|
||||
}
|
||||
|
||||
std::string Disassembler::cc(int flag) {
|
||||
std::string EightBit::Disassembler::cc(int flag) {
|
||||
switch (flag) {
|
||||
case 0:
|
||||
return "NZ";
|
||||
@ -117,7 +117,7 @@ std::string Disassembler::cc(int flag) {
|
||||
throw std::logic_error("Unhandled condition");
|
||||
}
|
||||
|
||||
std::string Disassembler::alu(int which) {
|
||||
std::string EightBit::Disassembler::alu(int which) {
|
||||
switch (which) {
|
||||
case 0: // ADD A,n
|
||||
return "ADD";
|
||||
@ -139,14 +139,14 @@ std::string Disassembler::alu(int which) {
|
||||
throw std::logic_error("Unhandled alu operation");
|
||||
}
|
||||
|
||||
std::string Disassembler::disassemble(LR35902& cpu) {
|
||||
std::string EightBit::Disassembler::disassemble(LR35902& cpu) {
|
||||
m_prefixCB = false;
|
||||
std::ostringstream output;
|
||||
disassemble(output, cpu, cpu.getProgramCounter().word);
|
||||
return output.str();
|
||||
}
|
||||
|
||||
void Disassembler::disassemble(std::ostringstream& output, LR35902& cpu, uint16_t pc) {
|
||||
void EightBit::Disassembler::disassemble(std::ostringstream& output, LR35902& cpu, uint16_t pc) {
|
||||
|
||||
auto& memory = cpu.getMemory();
|
||||
auto opcode = memory.peek(pc);
|
||||
@ -190,7 +190,7 @@ void Disassembler::disassemble(std::ostringstream& output, LR35902& cpu, uint16_
|
||||
output << m_formatter % (int)immediate % (int)absolute % relative % (int)displacement % indexedImmediate;
|
||||
}
|
||||
|
||||
void Disassembler::disassembleCB(
|
||||
void EightBit::Disassembler::disassembleCB(
|
||||
std::ostringstream& output,
|
||||
LR35902& cpu,
|
||||
uint16_t pc,
|
||||
@ -240,7 +240,7 @@ void Disassembler::disassembleCB(
|
||||
}
|
||||
}
|
||||
|
||||
void Disassembler::disassembleOther(
|
||||
void EightBit::Disassembler::disassembleOther(
|
||||
std::ostringstream& output,
|
||||
LR35902& cpu,
|
||||
uint16_t pc,
|
||||
@ -504,13 +504,13 @@ void Disassembler::disassembleOther(
|
||||
}
|
||||
}
|
||||
|
||||
std::string Disassembler::flag(uint8_t value, int flag, const std::string& represents) {
|
||||
std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string& represents) {
|
||||
std::ostringstream output;
|
||||
output << (value & flag ? represents : "-");
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::flags(uint8_t value) {
|
||||
std::string EightBit::Disassembler::flags(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output
|
||||
<< flag(value, LR35902::ZF, "Z")
|
||||
@ -524,31 +524,31 @@ std::string Disassembler::flags(uint8_t value) {
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::hex(uint8_t value) {
|
||||
std::string EightBit::Disassembler::hex(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::hex(uint16_t value) {
|
||||
std::string EightBit::Disassembler::hex(uint16_t value) {
|
||||
std::ostringstream output;
|
||||
output << std::hex << std::setw(4) << std::setfill('0') << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::binary(uint8_t value) {
|
||||
std::string EightBit::Disassembler::binary(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << std::bitset<8>(value);
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::decimal(uint8_t value) {
|
||||
std::string EightBit::Disassembler::decimal(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembler::invalid(uint8_t value) {
|
||||
std::string EightBit::Disassembler::invalid(uint8_t value) {
|
||||
std::ostringstream output;
|
||||
output << "Invalid instruction: " << hex(value) << "(" << binary(value) << ")";
|
||||
return output.str();
|
||||
|
@ -4,19 +4,19 @@
|
||||
// based on http://www.z80.info/decoding.htm
|
||||
// Half carry flag help from https://github.com/oubiwann/z80
|
||||
|
||||
LR35902::LR35902(Bus& memory)
|
||||
EightBit::LR35902::LR35902(Bus& memory)
|
||||
: Processor(memory),
|
||||
m_ime(false),
|
||||
m_prefixCB(false) {
|
||||
}
|
||||
|
||||
void LR35902::reset() {
|
||||
void EightBit::LR35902::reset() {
|
||||
Processor::reset();
|
||||
sp.word = 0xfffe;
|
||||
di();
|
||||
}
|
||||
|
||||
void LR35902::initialise() {
|
||||
void EightBit::LR35902::initialise() {
|
||||
|
||||
Processor::initialise();
|
||||
|
||||
@ -28,42 +28,54 @@ void LR35902::initialise() {
|
||||
m_prefixCB = false;
|
||||
}
|
||||
|
||||
void LR35902::di() {
|
||||
#pragma region Interrupt routines
|
||||
|
||||
void EightBit::LR35902::di() {
|
||||
IME() = false;
|
||||
}
|
||||
|
||||
void LR35902::ei() {
|
||||
void EightBit::LR35902::ei() {
|
||||
IME() = true;
|
||||
}
|
||||
|
||||
int LR35902::interrupt(uint8_t value) {
|
||||
int EightBit::LR35902::interrupt(uint8_t value) {
|
||||
cycles = 0;
|
||||
di();
|
||||
restart(value);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void LR35902::adjustZero(uint8_t value) {
|
||||
#pragma endregion Interrupt routines
|
||||
|
||||
#pragma region Flag manipulation helpers
|
||||
|
||||
void EightBit::LR35902::adjustZero(uint8_t value) {
|
||||
clearFlag(ZF, value);
|
||||
}
|
||||
|
||||
void LR35902::postIncrement(uint8_t value) {
|
||||
void EightBit::LR35902::postIncrement(uint8_t value) {
|
||||
adjustZero(value);
|
||||
clearFlag(NF);
|
||||
clearFlag(HC, lowNibble(value));
|
||||
}
|
||||
|
||||
void LR35902::postDecrement(uint8_t value) {
|
||||
void EightBit::LR35902::postDecrement(uint8_t value) {
|
||||
adjustZero(value);
|
||||
setFlag(NF);
|
||||
clearFlag(HC, lowNibble(value + 1));
|
||||
}
|
||||
|
||||
void LR35902::restart(uint8_t address) {
|
||||
#pragma endregion Flag manipulation helpers
|
||||
|
||||
#pragma region PC manipulation: call/ret/jp/jr
|
||||
|
||||
void EightBit::LR35902::restart(uint8_t address) {
|
||||
pushWord(pc);
|
||||
pc.word = address;
|
||||
pc.low = address;
|
||||
pc.high = 0;
|
||||
}
|
||||
|
||||
void LR35902::jrConditional(int conditional) {
|
||||
void EightBit::LR35902::jrConditional(int conditional) {
|
||||
auto offset = (int8_t)fetchByte();
|
||||
if (conditional) {
|
||||
pc.word += offset;
|
||||
@ -71,7 +83,7 @@ void LR35902::jrConditional(int conditional) {
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::jrConditionalFlag(int flag) {
|
||||
void EightBit::LR35902::jrConditionalFlag(int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
jrConditional(!(F() & ZF));
|
||||
@ -94,7 +106,7 @@ void LR35902::jrConditionalFlag(int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::jumpConditional(int conditional) {
|
||||
void EightBit::LR35902::jumpConditional(int conditional) {
|
||||
auto address = fetchWord();
|
||||
if (conditional) {
|
||||
pc = address;
|
||||
@ -102,7 +114,7 @@ void LR35902::jumpConditional(int conditional) {
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::jumpConditionalFlag(int flag) {
|
||||
void EightBit::LR35902::jumpConditionalFlag(int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
jumpConditional(!(F() & ZF));
|
||||
@ -138,23 +150,23 @@ void LR35902::jumpConditionalFlag(int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::ret() {
|
||||
void EightBit::LR35902::ret() {
|
||||
popWord(pc);
|
||||
}
|
||||
|
||||
void LR35902::reti() {
|
||||
void EightBit::LR35902::reti() {
|
||||
ret();
|
||||
ei();
|
||||
}
|
||||
|
||||
void LR35902::returnConditional(int condition) {
|
||||
void EightBit::LR35902::returnConditional(int condition) {
|
||||
if (condition) {
|
||||
ret();
|
||||
cycles += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::returnConditionalFlag(int flag) {
|
||||
void EightBit::LR35902::returnConditionalFlag(int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
returnConditional(!(F() & ZF));
|
||||
@ -199,19 +211,19 @@ void LR35902::returnConditionalFlag(int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::call(uint16_t address) {
|
||||
void EightBit::LR35902::call(uint16_t address) {
|
||||
pushWord(pc);
|
||||
pc.word = address;
|
||||
}
|
||||
|
||||
void LR35902::callConditional(uint16_t address, int condition) {
|
||||
void EightBit::LR35902::callConditional(uint16_t address, int condition) {
|
||||
if (condition) {
|
||||
call(address);
|
||||
cycles += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::callConditionalFlag(uint16_t address, int flag) {
|
||||
void EightBit::LR35902::callConditionalFlag(uint16_t address, int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
callConditional(address, !(F() & ZF));
|
||||
@ -234,18 +246,22 @@ void LR35902::callConditionalFlag(uint16_t address, int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t LR35902::sbc(uint16_t value) {
|
||||
#pragma endregion PC manipulation: call/ret/jp/jr
|
||||
|
||||
#pragma region 16-bit arithmetic
|
||||
|
||||
uint16_t EightBit::LR35902::sbc(uint16_t value) {
|
||||
|
||||
auto hl = RP(HL_IDX);
|
||||
|
||||
auto high = hl.high;
|
||||
auto highValue = EightBit::Memory::highByte(value);
|
||||
auto highValue = Memory::highByte(value);
|
||||
auto applyCarry = F() & CF;
|
||||
|
||||
uint32_t result = (int)hl.word - (int)value;
|
||||
if (applyCarry)
|
||||
--result;
|
||||
auto highResult = EightBit::Memory::highByte(result);
|
||||
auto highResult = Memory::highByte(result);
|
||||
|
||||
adjustZero(result);
|
||||
adjustHalfCarrySub(high, highValue, highResult);
|
||||
@ -256,18 +272,18 @@ uint16_t LR35902::sbc(uint16_t value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t LR35902::adc(uint16_t value) {
|
||||
uint16_t EightBit::LR35902::adc(uint16_t value) {
|
||||
|
||||
auto hl = RP(HL_IDX);
|
||||
|
||||
auto high = hl.high;
|
||||
auto highValue = EightBit::Memory::highByte(value);
|
||||
auto highValue = Memory::highByte(value);
|
||||
auto applyCarry = F() & CF;
|
||||
|
||||
uint32_t result = (int)hl.word + (int)value;
|
||||
if (applyCarry)
|
||||
++result;
|
||||
auto highResult = EightBit::Memory::highByte(result);
|
||||
auto highResult = Memory::highByte(result);
|
||||
|
||||
adjustZero(result);
|
||||
adjustHalfCarryAdd(high, highValue, highResult);
|
||||
@ -278,16 +294,16 @@ uint16_t LR35902::adc(uint16_t value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t LR35902::add(uint16_t value) {
|
||||
uint16_t EightBit::LR35902::add(uint16_t value) {
|
||||
|
||||
auto hl = RP(HL_IDX);
|
||||
|
||||
auto high = hl.high;
|
||||
auto highValue = EightBit::Memory::highByte(value);
|
||||
auto highValue = Memory::highByte(value);
|
||||
|
||||
uint32_t result = (int)hl.word + (int)value;
|
||||
|
||||
auto highResult = EightBit::Memory::highByte(result);
|
||||
auto highResult = Memory::highByte(result);
|
||||
|
||||
clearFlag(NF);
|
||||
setFlag(CF, result & Bit16);
|
||||
@ -296,7 +312,11 @@ uint16_t LR35902::add(uint16_t value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void LR35902::sub(uint8_t& operand, uint8_t value, bool carry) {
|
||||
#pragma endregion 16-bit arithmetic
|
||||
|
||||
#pragma region ALU
|
||||
|
||||
void EightBit::LR35902::sub(uint8_t& operand, uint8_t value, bool carry) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
@ -304,7 +324,7 @@ void LR35902::sub(uint8_t& operand, uint8_t value, bool carry) {
|
||||
if (carry && (F() & CF))
|
||||
--result;
|
||||
|
||||
operand = EightBit::Memory::lowByte(result);
|
||||
operand = Memory::lowByte(result);
|
||||
|
||||
adjustZero(operand);
|
||||
adjustHalfCarrySub(before, value, result);
|
||||
@ -312,15 +332,15 @@ void LR35902::sub(uint8_t& operand, uint8_t value, bool carry) {
|
||||
setFlag(CF, result & Bit8);
|
||||
}
|
||||
|
||||
void LR35902::sbc(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::LR35902::sbc(uint8_t& operand, uint8_t value) {
|
||||
sub(operand, value, true);
|
||||
}
|
||||
|
||||
void LR35902::sub(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::LR35902::sub(uint8_t& operand, uint8_t value) {
|
||||
sub(operand, value, false);
|
||||
}
|
||||
|
||||
void LR35902::add(uint8_t& operand, uint8_t value, bool carry) {
|
||||
void EightBit::LR35902::add(uint8_t& operand, uint8_t value, bool carry) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
@ -328,7 +348,7 @@ void LR35902::add(uint8_t& operand, uint8_t value, bool carry) {
|
||||
if (carry && (F() & CF))
|
||||
++result;
|
||||
|
||||
operand = EightBit::Memory::lowByte(result);
|
||||
operand = Memory::lowByte(result);
|
||||
|
||||
adjustZero(operand);
|
||||
adjustHalfCarryAdd(before, value, result);
|
||||
@ -336,47 +356,49 @@ void LR35902::add(uint8_t& operand, uint8_t value, bool carry) {
|
||||
setFlag(CF, result & Bit8);
|
||||
}
|
||||
|
||||
void LR35902::adc(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::LR35902::adc(uint8_t& operand, uint8_t value) {
|
||||
add(operand, value, true);
|
||||
}
|
||||
|
||||
void LR35902::add(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::LR35902::add(uint8_t& operand, uint8_t value) {
|
||||
add(operand, value, false);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void LR35902::andr(uint8_t& operand, uint8_t value) {
|
||||
void EightBit::LR35902::andr(uint8_t& operand, uint8_t value) {
|
||||
setFlag(HC);
|
||||
clearFlag(CF | NF);
|
||||
operand &= value;
|
||||
adjustZero(operand);
|
||||
}
|
||||
|
||||
void LR35902::anda(uint8_t value) {
|
||||
void EightBit::LR35902::anda(uint8_t value) {
|
||||
andr(A(), value);
|
||||
}
|
||||
|
||||
void LR35902::xora(uint8_t value) {
|
||||
void EightBit::LR35902::xora(uint8_t value) {
|
||||
clearFlag(HC | CF | NF);
|
||||
A() ^= value;
|
||||
adjustZero(A());
|
||||
}
|
||||
|
||||
void LR35902::ora(uint8_t value) {
|
||||
void EightBit::LR35902::ora(uint8_t value) {
|
||||
clearFlag(HC | CF | NF);
|
||||
A() |= value;
|
||||
adjustZero(A());
|
||||
}
|
||||
|
||||
void LR35902::compare(uint8_t value) {
|
||||
void EightBit::LR35902::compare(uint8_t value) {
|
||||
auto check = A();
|
||||
sub(check, value);
|
||||
}
|
||||
|
||||
//
|
||||
#pragma endregion ALU
|
||||
|
||||
void LR35902::rlc(uint8_t& operand) {
|
||||
#pragma region Shift and rotate
|
||||
|
||||
void EightBit::LR35902::rlc(uint8_t& operand) {
|
||||
auto carry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
setFlag(CF, carry);
|
||||
@ -385,7 +407,7 @@ void LR35902::rlc(uint8_t& operand) {
|
||||
adjustZero(operand);
|
||||
}
|
||||
|
||||
void LR35902::rrc(uint8_t& operand) {
|
||||
void EightBit::LR35902::rrc(uint8_t& operand) {
|
||||
auto carry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
carry ? operand |= Bit7 : operand &= ~Bit7;
|
||||
@ -394,7 +416,7 @@ void LR35902::rrc(uint8_t& operand) {
|
||||
adjustZero(operand);
|
||||
}
|
||||
|
||||
void LR35902::rl(uint8_t& operand) {
|
||||
void EightBit::LR35902::rl(uint8_t& operand) {
|
||||
auto oldCarry = F() & CF;
|
||||
auto newCarry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
@ -404,7 +426,7 @@ void LR35902::rl(uint8_t& operand) {
|
||||
adjustZero(operand);
|
||||
}
|
||||
|
||||
void LR35902::rr(uint8_t& operand) {
|
||||
void EightBit::LR35902::rr(uint8_t& operand) {
|
||||
auto oldCarry = F() & CF;
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
@ -416,7 +438,7 @@ void LR35902::rr(uint8_t& operand) {
|
||||
|
||||
//
|
||||
|
||||
void LR35902::sla(uint8_t& operand) {
|
||||
void EightBit::LR35902::sla(uint8_t& operand) {
|
||||
auto newCarry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
setFlag(CF, newCarry);
|
||||
@ -424,7 +446,7 @@ void LR35902::sla(uint8_t& operand) {
|
||||
adjustZero(operand);
|
||||
}
|
||||
|
||||
void LR35902::sra(uint8_t& operand) {
|
||||
void EightBit::LR35902::sra(uint8_t& operand) {
|
||||
auto new7 = operand & Bit7;
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
@ -434,7 +456,7 @@ void LR35902::sra(uint8_t& operand) {
|
||||
adjustZero(operand);
|
||||
}
|
||||
|
||||
void LR35902::srl(uint8_t& operand) {
|
||||
void EightBit::LR35902::srl(uint8_t& operand) {
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
operand &= ~Bit7; // clear bit 7
|
||||
@ -445,44 +467,48 @@ void LR35902::srl(uint8_t& operand) {
|
||||
|
||||
//
|
||||
|
||||
void LR35902::rlca() {
|
||||
void EightBit::LR35902::rlca() {
|
||||
rlc(A());
|
||||
}
|
||||
|
||||
void LR35902::rrca() {
|
||||
void EightBit::LR35902::rrca() {
|
||||
rrc(A());
|
||||
}
|
||||
|
||||
void LR35902::rla() {
|
||||
void EightBit::LR35902::rla() {
|
||||
rl(A());
|
||||
}
|
||||
|
||||
void LR35902::rra() {
|
||||
void EightBit::LR35902::rra() {
|
||||
rr(A());
|
||||
}
|
||||
|
||||
//
|
||||
#pragma endregion Shift and rotate
|
||||
|
||||
void LR35902::bit(int n, uint8_t& operand) {
|
||||
#pragma region BIT/SET/RES
|
||||
|
||||
void EightBit::LR35902::bit(int n, uint8_t& operand) {
|
||||
auto carry = F() & CF;
|
||||
uint8_t discarded = operand;
|
||||
andr(discarded, 1 << n);
|
||||
setFlag(CF, carry);
|
||||
}
|
||||
|
||||
void LR35902::res(int n, uint8_t& operand) {
|
||||
void EightBit::LR35902::res(int n, uint8_t& operand) {
|
||||
auto bit = 1 << n;
|
||||
operand &= ~bit;
|
||||
}
|
||||
|
||||
void LR35902::set(int n, uint8_t& operand) {
|
||||
void EightBit::LR35902::set(int n, uint8_t& operand) {
|
||||
auto bit = 1 << n;
|
||||
operand |= bit;
|
||||
}
|
||||
|
||||
//
|
||||
#pragma endregion BIT/SET/RES
|
||||
|
||||
void LR35902::daa() {
|
||||
#pragma region Miscellaneous instructions
|
||||
|
||||
void EightBit::LR35902::daa() {
|
||||
|
||||
uint8_t a = A();
|
||||
|
||||
@ -508,23 +534,23 @@ void LR35902::daa() {
|
||||
A() = a;
|
||||
}
|
||||
|
||||
void LR35902::cpl() {
|
||||
void EightBit::LR35902::cpl() {
|
||||
A() = ~A();
|
||||
setFlag(HC | NF);
|
||||
}
|
||||
|
||||
void LR35902::scf() {
|
||||
void EightBit::LR35902::scf() {
|
||||
setFlag(CF);
|
||||
clearFlag(HC | NF);
|
||||
}
|
||||
|
||||
void LR35902::ccf() {
|
||||
void EightBit::LR35902::ccf() {
|
||||
auto carry = F() & CF;
|
||||
clearFlag(CF, carry);
|
||||
clearFlag(NF | HC);
|
||||
}
|
||||
|
||||
void LR35902::swap(uint8_t& operand) {
|
||||
void EightBit::LR35902::swap(uint8_t& operand) {
|
||||
auto low = lowNibble(operand);
|
||||
auto high = highNibble(operand);
|
||||
operand = promoteNibble(low) | demoteNibble(high);
|
||||
@ -532,13 +558,16 @@ void LR35902::swap(uint8_t& operand) {
|
||||
clearFlag(NF | HC | CF);
|
||||
}
|
||||
|
||||
int LR35902::step() {
|
||||
#pragma endregion Miscellaneous instructions
|
||||
|
||||
int EightBit::LR35902::step() {
|
||||
ExecutingInstruction.fire(*this);
|
||||
m_prefixCB = false;
|
||||
cycles = 0;
|
||||
return fetchExecute();
|
||||
}
|
||||
|
||||
int LR35902::execute(uint8_t opcode) {
|
||||
int EightBit::LR35902::execute(uint8_t opcode) {
|
||||
|
||||
auto x = (opcode & 0b11000000) >> 6;
|
||||
auto y = (opcode & 0b111000) >> 3;
|
||||
@ -547,8 +576,6 @@ int LR35902::execute(uint8_t opcode) {
|
||||
auto p = (y & 0b110) >> 1;
|
||||
auto q = (y & 1);
|
||||
|
||||
cycles = 0;
|
||||
|
||||
if (m_prefixCB)
|
||||
executeCB(x, y, z, p, q);
|
||||
else
|
||||
@ -560,7 +587,7 @@ int LR35902::execute(uint8_t opcode) {
|
||||
return cycles * 4;
|
||||
}
|
||||
|
||||
void LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
void EightBit::LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
switch (x) {
|
||||
case 0: // rot[y] r[z]
|
||||
switch (y) {
|
||||
@ -615,7 +642,7 @@ void LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
}
|
||||
|
||||
void LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
switch (z) {
|
||||
|
@ -2,13 +2,13 @@
|
||||
#include "Profiler.h"
|
||||
#include "LR35902.h"
|
||||
|
||||
Profiler::Profiler(LR35902& cpu)
|
||||
EightBit::Profiler::Profiler(LR35902& cpu)
|
||||
: m_cpu(cpu) {
|
||||
std::fill(m_instructions.begin(), m_instructions.end(), 0);
|
||||
std::fill(m_addresses.begin(), m_addresses.end(), 0);
|
||||
}
|
||||
|
||||
void Profiler::add(uint16_t address, uint8_t instruction) {
|
||||
void EightBit::Profiler::add(uint16_t address, uint8_t instruction) {
|
||||
|
||||
m_instructions[instruction]++;
|
||||
|
||||
@ -19,12 +19,12 @@ void Profiler::add(uint16_t address, uint8_t instruction) {
|
||||
m_addresses[address]++;
|
||||
}
|
||||
|
||||
void Profiler::dump() const {
|
||||
void EightBit::Profiler::dump() const {
|
||||
dumpInstructionProfiles();
|
||||
dumpAddressProfiles();
|
||||
}
|
||||
|
||||
void Profiler::dumpInstructionProfiles() const {
|
||||
void EightBit::Profiler::dumpInstructionProfiles() const {
|
||||
std::cout << "** instructions" << std::endl;
|
||||
for (int i = 0; i < 0x100; ++i) {
|
||||
auto count = m_instructions[i];
|
||||
@ -33,7 +33,7 @@ void Profiler::dumpInstructionProfiles() const {
|
||||
}
|
||||
}
|
||||
|
||||
void Profiler::dumpAddressProfiles() const {
|
||||
void EightBit::Profiler::dumpAddressProfiles() const {
|
||||
std::cout << "** addresses" << std::endl;
|
||||
for (int i = 0; i < 0x10000; ++i) {
|
||||
auto count = m_addresses[i];
|
||||
|
Loading…
Reference in New Issue
Block a user