mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-02 18:29:41 +00:00
Introduce an IntelProcessor base class to allow known good implementation to be shared.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
b1aa523dcc
commit
627e41bf35
@ -2,12 +2,12 @@
|
||||
|
||||
// Auxiliary carry logic from https://github.com/begoon/i8080-core
|
||||
|
||||
#include "Processor.h"
|
||||
#include "IntelProcessor.h"
|
||||
#include "StatusFlags.h"
|
||||
#include "InputOutput.h"
|
||||
|
||||
namespace EightBit {
|
||||
class Intel8080 : public Processor {
|
||||
class Intel8080 : public IntelProcessor {
|
||||
public:
|
||||
typedef std::function<void()> instruction_t;
|
||||
|
||||
@ -69,9 +69,6 @@ namespace EightBit {
|
||||
|
||||
std::array<Instruction, 0x100> instructions;
|
||||
|
||||
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 } };
|
||||
|
||||
uint8_t a;
|
||||
StatusFlags f;
|
||||
|
||||
@ -104,28 +101,22 @@ namespace EightBit {
|
||||
adjustParity(value);
|
||||
}
|
||||
|
||||
int buildAuxiliaryCarryIndex(uint8_t value, int calculation) {
|
||||
return ((A() & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
}
|
||||
|
||||
void adjustAuxiliaryCarryAdd(uint8_t value, int calculation) {
|
||||
auto index = buildAuxiliaryCarryIndex(value, calculation);
|
||||
F().AC = m_halfCarryTableAdd[index & 0x7];
|
||||
F().AC = calculateHalfCarryAdd(A(), value, calculation);
|
||||
}
|
||||
|
||||
void adjustAuxiliaryCarrySub(uint8_t value, int calculation) {
|
||||
auto index = buildAuxiliaryCarryIndex(value, calculation);
|
||||
F().AC = !m_halfCarryTableSub[index & 0x7];
|
||||
F().AC = !calculateHalfCarrySub(A(), value, calculation);
|
||||
}
|
||||
|
||||
void postIncrement(uint8_t value) {
|
||||
adjustSZP(value);
|
||||
F().AC = (value & 0x0f) == 0;
|
||||
F().AC = lowNibble(value) == 0;
|
||||
}
|
||||
|
||||
void postDecrement(uint8_t value) {
|
||||
adjustSZP(value);
|
||||
F().AC = (value & 0x0f) != 0xf;
|
||||
F().AC = lowNibble(value) != 0xf;
|
||||
}
|
||||
|
||||
static Instruction INS(instruction_t method, AddressingMode mode, std::string disassembly, int cycles);
|
||||
@ -135,14 +126,6 @@ namespace EightBit {
|
||||
|
||||
//
|
||||
|
||||
register16_t fetchWord() {
|
||||
register16_t returned;
|
||||
Processor::fetchWord(returned);
|
||||
return returned;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void compare(uint8_t value) {
|
||||
uint16_t subtraction = A() - value;
|
||||
adjustSZP((uint8_t)subtraction);
|
||||
@ -164,9 +147,9 @@ namespace EightBit {
|
||||
}
|
||||
|
||||
void jmpConditional(int conditional) {
|
||||
auto destination = fetchWord();
|
||||
fetchWord();
|
||||
if (conditional)
|
||||
pc = destination;
|
||||
pc = MEMPTR();
|
||||
}
|
||||
|
||||
void callConditional(int condition) {
|
||||
@ -344,22 +327,23 @@ namespace EightBit {
|
||||
void ldax_d() { A() = m_memory.get(DE().word); }
|
||||
|
||||
void sta() {
|
||||
auto destination = fetchWord();
|
||||
m_memory.set(destination.word, A());
|
||||
fetchWord();
|
||||
m_memory.set(MEMPTR().word, A());
|
||||
}
|
||||
|
||||
void lda() {
|
||||
auto source = fetchWord();
|
||||
A() = m_memory.get(source.word);
|
||||
fetchWord();
|
||||
A() = m_memory.get(MEMPTR().word);
|
||||
}
|
||||
|
||||
void shld() {
|
||||
auto destination = fetchWord();
|
||||
m_memory.setWord(destination.word, HL());
|
||||
fetchWord();
|
||||
m_memory.setWord(MEMPTR().word, HL());
|
||||
}
|
||||
|
||||
void lhld() {
|
||||
HL() = m_memory.getWord(fetchWord().word);
|
||||
fetchWord();
|
||||
HL() = m_memory.getWord(MEMPTR().word);
|
||||
}
|
||||
|
||||
void xchg() {
|
||||
@ -427,7 +411,7 @@ namespace EightBit {
|
||||
|
||||
// call
|
||||
|
||||
void call() {
|
||||
virtual void call() override {
|
||||
auto destination = m_memory.getWord(pc.word);
|
||||
callAddress(destination.word);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "Disassembler.h"
|
||||
|
||||
EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports)
|
||||
: Processor(memory),
|
||||
: IntelProcessor(memory),
|
||||
a(0),
|
||||
f(0),
|
||||
m_interrupt(false),
|
||||
|
@ -2,11 +2,12 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "Processor.h"
|
||||
#include "IntelProcessor.h"
|
||||
#include "Bus.h"
|
||||
#include "Signal.h"
|
||||
|
||||
namespace EightBit {
|
||||
class LR35902 : public Processor {
|
||||
class LR35902 : public IntelProcessor {
|
||||
public:
|
||||
enum StatusBits {
|
||||
ZF = Bit7,
|
||||
@ -64,8 +65,6 @@ namespace EightBit {
|
||||
uint8_t& H() { return HL().high; }
|
||||
uint8_t& L() { return HL().low; }
|
||||
|
||||
register16_t& MEMPTR() { return m_memptr; }
|
||||
|
||||
virtual void reset();
|
||||
virtual void initialise();
|
||||
|
||||
@ -77,8 +76,6 @@ namespace EightBit {
|
||||
|
||||
bool m_ime;
|
||||
|
||||
register16_t m_memptr;
|
||||
|
||||
bool m_prefixCB;
|
||||
|
||||
bool m_stopped;
|
||||
@ -86,10 +83,6 @@ namespace EightBit {
|
||||
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 } };
|
||||
|
||||
void fetchWord() {
|
||||
Processor::fetchWord(MEMPTR());
|
||||
}
|
||||
|
||||
int fetchExecute() {
|
||||
return execute(fetchByte());
|
||||
}
|
||||
@ -146,18 +139,12 @@ namespace EightBit {
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
setFlag(HC, calculateHalfCarryAdd(before, value, calculation));
|
||||
}
|
||||
|
||||
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
|
||||
setFlag(HC, calculateHalfCarrySub(before, value, calculation));
|
||||
}
|
||||
|
||||
void executeCB(int x, int y, int z, int p, int q);
|
||||
@ -182,7 +169,6 @@ namespace EightBit {
|
||||
void jumpConditional(int condition);
|
||||
void jumpConditionalFlag(int flag);
|
||||
|
||||
void call();
|
||||
void callConditional(int condition);
|
||||
void callConditionalFlag(int flag);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// Half carry flag help from https://github.com/oubiwann/z80
|
||||
|
||||
EightBit::LR35902::LR35902(Bus& memory)
|
||||
: Processor(memory),
|
||||
: IntelProcessor(memory),
|
||||
m_ime(false),
|
||||
m_prefixCB(false) {
|
||||
MEMPTR().word = 0;
|
||||
@ -214,11 +214,6 @@ void EightBit::LR35902::returnConditionalFlag(int flag) {
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::LR35902::call() {
|
||||
pushWord(pc);
|
||||
pc = MEMPTR();
|
||||
}
|
||||
|
||||
void EightBit::LR35902::callConditional(int condition) {
|
||||
if (condition) {
|
||||
call();
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "Processor.h"
|
||||
#include "IntelProcessor.h"
|
||||
#include "InputOutput.h"
|
||||
|
||||
namespace EightBit {
|
||||
class Z80 : public Processor {
|
||||
class Z80 : public IntelProcessor {
|
||||
public:
|
||||
enum StatusBits {
|
||||
SF = Bit7,
|
||||
@ -82,8 +82,6 @@ namespace EightBit {
|
||||
bool& IFF1() { return m_iff1; }
|
||||
bool& IFF2() { return m_iff2; }
|
||||
|
||||
register16_t& MEMPTR() { return m_memptr; }
|
||||
|
||||
bool& M1() { return m1; }
|
||||
|
||||
void exx() {
|
||||
@ -97,7 +95,7 @@ namespace EightBit {
|
||||
virtual void reset();
|
||||
virtual void initialise();
|
||||
|
||||
private:
|
||||
protected:
|
||||
InputOutput& m_ports;
|
||||
|
||||
enum { BC_IDX, DE_IDX, HL_IDX };
|
||||
@ -117,8 +115,6 @@ namespace EightBit {
|
||||
bool m_iff1;
|
||||
bool m_iff2;
|
||||
|
||||
register16_t m_memptr;
|
||||
|
||||
bool m1;
|
||||
|
||||
bool m_prefixCB;
|
||||
@ -128,13 +124,6 @@ namespace EightBit {
|
||||
|
||||
int8_t m_displacement;
|
||||
|
||||
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 } };
|
||||
|
||||
void fetchWord() {
|
||||
Processor::fetchWord(MEMPTR());
|
||||
}
|
||||
|
||||
int fetchExecute() {
|
||||
M1() = true;
|
||||
return execute(fetchByteExecute());
|
||||
@ -299,18 +288,12 @@ namespace EightBit {
|
||||
adc(hl, operand);
|
||||
}
|
||||
|
||||
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]);
|
||||
setFlag(HC, calculateHalfCarryAdd(before, value, calculation));
|
||||
}
|
||||
|
||||
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
|
||||
setFlag(HC, calculateHalfCarrySub(before, value, calculation));
|
||||
}
|
||||
|
||||
void adjustOverflowAdd(uint8_t before, uint8_t value, uint8_t calculation) {
|
||||
@ -362,7 +345,7 @@ namespace EightBit {
|
||||
void jumpConditional(int condition);
|
||||
void jumpConditionalFlag(int flag);
|
||||
|
||||
void call();
|
||||
virtual void call() override;
|
||||
void callConditional(int condition);
|
||||
void callConditionalFlag(int flag);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// Half carry flag help from https://github.com/oubiwann/z80
|
||||
|
||||
EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
|
||||
: Processor(memory),
|
||||
: IntelProcessor(memory),
|
||||
m_ports(ports),
|
||||
m_registerSet(0),
|
||||
m_accumulatorFlagsSet(0),
|
||||
@ -21,17 +21,16 @@ EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
|
||||
m_prefixFD(false) {
|
||||
IX().word = 0xffff;
|
||||
IY().word = 0xffff;
|
||||
MEMPTR().word = 0;
|
||||
}
|
||||
|
||||
void EightBit::Z80::reset() {
|
||||
Processor::reset();
|
||||
IntelProcessor::reset();
|
||||
IFF1() = IFF2() = false;
|
||||
}
|
||||
|
||||
void EightBit::Z80::initialise() {
|
||||
|
||||
Processor::initialise();
|
||||
IntelProcessor::initialise();
|
||||
|
||||
IM() = 0;
|
||||
|
||||
@ -55,7 +54,6 @@ void EightBit::Z80::initialise() {
|
||||
|
||||
REFRESH() = 0x7f;
|
||||
IV() = 0xff;
|
||||
MEMPTR().word = 0;
|
||||
|
||||
m_prefixCB = false;
|
||||
m_prefixDD = false;
|
||||
@ -294,8 +292,7 @@ void EightBit::Z80::returnConditionalFlag(int flag) {
|
||||
}
|
||||
|
||||
void EightBit::Z80::call() {
|
||||
pushWord(pc);
|
||||
pc = MEMPTR();
|
||||
IntelProcessor::call();
|
||||
cycles += 7;
|
||||
}
|
||||
|
||||
|
53
inc/IntelProcessor.h
Normal file
53
inc/IntelProcessor.h
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "Processor.h"
|
||||
|
||||
namespace EightBit {
|
||||
class IntelProcessor : public Processor
|
||||
{
|
||||
public:
|
||||
virtual ~IntelProcessor();
|
||||
|
||||
register16_t& MEMPTR() { return m_memptr; }
|
||||
|
||||
virtual void initialise();
|
||||
|
||||
protected:
|
||||
IntelProcessor(Memory& memory);
|
||||
|
||||
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 } };
|
||||
|
||||
int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) {
|
||||
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
}
|
||||
|
||||
bool calculateHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
return m_halfCarryTableAdd[index & 0x7];
|
||||
}
|
||||
|
||||
bool calculateHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||
return m_halfCarryTableSub[index & 0x7];
|
||||
}
|
||||
|
||||
void push(uint8_t value);
|
||||
void pushWord(register16_t value);
|
||||
|
||||
uint8_t pop();
|
||||
void popWord(register16_t& output);
|
||||
|
||||
void fetchWord() {
|
||||
Processor::fetchWord(MEMPTR());
|
||||
}
|
||||
|
||||
virtual void call() {
|
||||
pushWord(pc);
|
||||
pc = MEMPTR();
|
||||
}
|
||||
|
||||
private:
|
||||
register16_t m_memptr;
|
||||
};
|
||||
}
|
@ -44,8 +44,6 @@ namespace EightBit {
|
||||
static uint8_t promoteNibble(uint8_t value) { return value << 4; }
|
||||
static uint8_t demoteNibble(uint8_t value) { return highNibble(value); }
|
||||
|
||||
Processor(Memory& memory);
|
||||
|
||||
const Memory& getMemory() const { return m_memory; }
|
||||
|
||||
register16_t getProgramCounter() const { return pc; }
|
||||
@ -62,6 +60,8 @@ namespace EightBit {
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
Processor(Memory& memory);
|
||||
|
||||
Memory& m_memory;
|
||||
|
||||
int cycles;
|
||||
@ -71,12 +71,6 @@ namespace EightBit {
|
||||
|
||||
bool m_halted;
|
||||
|
||||
void push(uint8_t value);
|
||||
void pushWord(register16_t value);
|
||||
|
||||
uint8_t pop();
|
||||
void popWord(register16_t& output);
|
||||
|
||||
uint8_t fetchByte() {
|
||||
m_memory.ADDRESS().word = pc.word++;
|
||||
return m_memory.reference();
|
||||
|
@ -143,6 +143,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\inc\EventArgs.h" />
|
||||
<ClInclude Include="..\inc\IntelProcessor.h" />
|
||||
<ClInclude Include="..\inc\Memory.h" />
|
||||
<ClInclude Include="..\inc\Processor.h" />
|
||||
<ClInclude Include="..\inc\Signal.h" />
|
||||
@ -150,6 +151,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="EventArgs.cpp" />
|
||||
<ClCompile Include="IntelProcessor.cpp" />
|
||||
<ClCompile Include="Memory.cpp" />
|
||||
<ClCompile Include="Processor.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
@ -26,6 +26,9 @@
|
||||
<ClInclude Include="..\inc\Signal.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\IntelProcessor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
@ -40,5 +43,8 @@
|
||||
<ClCompile Include="Processor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntelProcessor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
36
src/IntelProcessor.cpp
Normal file
36
src/IntelProcessor.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "stdafx.h"
|
||||
#include "IntelProcessor.h"
|
||||
|
||||
EightBit::IntelProcessor::IntelProcessor(Memory& memory)
|
||||
: Processor(memory) {
|
||||
MEMPTR().word = 0;
|
||||
}
|
||||
|
||||
EightBit::IntelProcessor::~IntelProcessor() {
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::initialise() {
|
||||
Processor::initialise();
|
||||
MEMPTR().word = 0;
|
||||
}
|
||||
|
||||
|
||||
void EightBit::IntelProcessor::push(uint8_t value) {
|
||||
m_memory.ADDRESS().word = --sp.word;
|
||||
m_memory.reference() = value;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::pushWord(register16_t value) {
|
||||
push(value.high);
|
||||
push(value.low);
|
||||
}
|
||||
|
||||
uint8_t EightBit::IntelProcessor::pop() {
|
||||
m_memory.ADDRESS().word = sp.word++;
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::popWord(register16_t& output) {
|
||||
output.low = pop();
|
||||
output.high = pop();
|
||||
}
|
@ -17,23 +17,3 @@ void EightBit::Processor::initialise() {
|
||||
sp.word = 0xffff;
|
||||
reset();
|
||||
}
|
||||
|
||||
void EightBit::Processor::push(uint8_t value) {
|
||||
m_memory.ADDRESS().word = --sp.word;
|
||||
m_memory.reference() = value;
|
||||
}
|
||||
|
||||
void EightBit::Processor::pushWord(register16_t value) {
|
||||
push(value.high);
|
||||
push(value.low);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::pop() {
|
||||
m_memory.ADDRESS().word = sp.word++;
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
void EightBit::Processor::popWord(register16_t& output) {
|
||||
output.low = pop();
|
||||
output.high = pop();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user