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:
Adrian.Conlon 2017-06-11 09:45:34 +01:00
parent b1aa523dcc
commit 627e41bf35
12 changed files with 133 additions and 117 deletions

View File

@ -2,12 +2,12 @@
// Auxiliary carry logic from https://github.com/begoon/i8080-core // Auxiliary carry logic from https://github.com/begoon/i8080-core
#include "Processor.h" #include "IntelProcessor.h"
#include "StatusFlags.h" #include "StatusFlags.h"
#include "InputOutput.h" #include "InputOutput.h"
namespace EightBit { namespace EightBit {
class Intel8080 : public Processor { class Intel8080 : public IntelProcessor {
public: public:
typedef std::function<void()> instruction_t; typedef std::function<void()> instruction_t;
@ -69,9 +69,6 @@ namespace EightBit {
std::array<Instruction, 0x100> instructions; 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; uint8_t a;
StatusFlags f; StatusFlags f;
@ -104,28 +101,22 @@ namespace EightBit {
adjustParity(value); 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) { void adjustAuxiliaryCarryAdd(uint8_t value, int calculation) {
auto index = buildAuxiliaryCarryIndex(value, calculation); F().AC = calculateHalfCarryAdd(A(), value, calculation);
F().AC = m_halfCarryTableAdd[index & 0x7];
} }
void adjustAuxiliaryCarrySub(uint8_t value, int calculation) { void adjustAuxiliaryCarrySub(uint8_t value, int calculation) {
auto index = buildAuxiliaryCarryIndex(value, calculation); F().AC = !calculateHalfCarrySub(A(), value, calculation);
F().AC = !m_halfCarryTableSub[index & 0x7];
} }
void postIncrement(uint8_t value) { void postIncrement(uint8_t value) {
adjustSZP(value); adjustSZP(value);
F().AC = (value & 0x0f) == 0; F().AC = lowNibble(value) == 0;
} }
void postDecrement(uint8_t value) { void postDecrement(uint8_t value) {
adjustSZP(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); 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) { void compare(uint8_t value) {
uint16_t subtraction = A() - value; uint16_t subtraction = A() - value;
adjustSZP((uint8_t)subtraction); adjustSZP((uint8_t)subtraction);
@ -164,9 +147,9 @@ namespace EightBit {
} }
void jmpConditional(int conditional) { void jmpConditional(int conditional) {
auto destination = fetchWord(); fetchWord();
if (conditional) if (conditional)
pc = destination; pc = MEMPTR();
} }
void callConditional(int condition) { void callConditional(int condition) {
@ -344,22 +327,23 @@ namespace EightBit {
void ldax_d() { A() = m_memory.get(DE().word); } void ldax_d() { A() = m_memory.get(DE().word); }
void sta() { void sta() {
auto destination = fetchWord(); fetchWord();
m_memory.set(destination.word, A()); m_memory.set(MEMPTR().word, A());
} }
void lda() { void lda() {
auto source = fetchWord(); fetchWord();
A() = m_memory.get(source.word); A() = m_memory.get(MEMPTR().word);
} }
void shld() { void shld() {
auto destination = fetchWord(); fetchWord();
m_memory.setWord(destination.word, HL()); m_memory.setWord(MEMPTR().word, HL());
} }
void lhld() { void lhld() {
HL() = m_memory.getWord(fetchWord().word); fetchWord();
HL() = m_memory.getWord(MEMPTR().word);
} }
void xchg() { void xchg() {
@ -427,7 +411,7 @@ namespace EightBit {
// call // call
void call() { virtual void call() override {
auto destination = m_memory.getWord(pc.word); auto destination = m_memory.getWord(pc.word);
callAddress(destination.word); callAddress(destination.word);
} }

View File

@ -5,7 +5,7 @@
#include "Disassembler.h" #include "Disassembler.h"
EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports) EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports)
: Processor(memory), : IntelProcessor(memory),
a(0), a(0),
f(0), f(0),
m_interrupt(false), m_interrupt(false),

View File

@ -2,11 +2,12 @@
#include <cstdint> #include <cstdint>
#include "Processor.h" #include "IntelProcessor.h"
#include "Bus.h" #include "Bus.h"
#include "Signal.h"
namespace EightBit { namespace EightBit {
class LR35902 : public Processor { class LR35902 : public IntelProcessor {
public: public:
enum StatusBits { enum StatusBits {
ZF = Bit7, ZF = Bit7,
@ -64,8 +65,6 @@ namespace EightBit {
uint8_t& H() { return HL().high; } uint8_t& H() { return HL().high; }
uint8_t& L() { return HL().low; } uint8_t& L() { return HL().low; }
register16_t& MEMPTR() { return m_memptr; }
virtual void reset(); virtual void reset();
virtual void initialise(); virtual void initialise();
@ -77,8 +76,6 @@ namespace EightBit {
bool m_ime; bool m_ime;
register16_t m_memptr;
bool m_prefixCB; bool m_prefixCB;
bool m_stopped; 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_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } }; std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
void fetchWord() {
Processor::fetchWord(MEMPTR());
}
int fetchExecute() { int fetchExecute() {
return execute(fetchByte()); 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) { void adjustHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
auto index = buildHalfCarryIndex(before, value, calculation); setFlag(HC, calculateHalfCarryAdd(before, value, calculation));
setFlag(HC, m_halfCarryTableAdd[index & 0x7]);
} }
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) { void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
auto index = buildHalfCarryIndex(before, value, calculation); setFlag(HC, calculateHalfCarrySub(before, value, calculation));
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
} }
void executeCB(int x, int y, int z, int p, int q); void executeCB(int x, int y, int z, int p, int q);
@ -182,7 +169,6 @@ namespace EightBit {
void jumpConditional(int condition); void jumpConditional(int condition);
void jumpConditionalFlag(int flag); void jumpConditionalFlag(int flag);
void call();
void callConditional(int condition); void callConditional(int condition);
void callConditionalFlag(int flag); void callConditionalFlag(int flag);

View File

@ -5,7 +5,7 @@
// Half carry flag help from https://github.com/oubiwann/z80 // Half carry flag help from https://github.com/oubiwann/z80
EightBit::LR35902::LR35902(Bus& memory) EightBit::LR35902::LR35902(Bus& memory)
: Processor(memory), : IntelProcessor(memory),
m_ime(false), m_ime(false),
m_prefixCB(false) { m_prefixCB(false) {
MEMPTR().word = 0; 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) { void EightBit::LR35902::callConditional(int condition) {
if (condition) { if (condition) {
call(); call();

View File

@ -2,11 +2,11 @@
#include <cstdint> #include <cstdint>
#include "Processor.h" #include "IntelProcessor.h"
#include "InputOutput.h" #include "InputOutput.h"
namespace EightBit { namespace EightBit {
class Z80 : public Processor { class Z80 : public IntelProcessor {
public: public:
enum StatusBits { enum StatusBits {
SF = Bit7, SF = Bit7,
@ -82,8 +82,6 @@ namespace EightBit {
bool& IFF1() { return m_iff1; } bool& IFF1() { return m_iff1; }
bool& IFF2() { return m_iff2; } bool& IFF2() { return m_iff2; }
register16_t& MEMPTR() { return m_memptr; }
bool& M1() { return m1; } bool& M1() { return m1; }
void exx() { void exx() {
@ -97,7 +95,7 @@ namespace EightBit {
virtual void reset(); virtual void reset();
virtual void initialise(); virtual void initialise();
private: protected:
InputOutput& m_ports; InputOutput& m_ports;
enum { BC_IDX, DE_IDX, HL_IDX }; enum { BC_IDX, DE_IDX, HL_IDX };
@ -117,8 +115,6 @@ namespace EightBit {
bool m_iff1; bool m_iff1;
bool m_iff2; bool m_iff2;
register16_t m_memptr;
bool m1; bool m1;
bool m_prefixCB; bool m_prefixCB;
@ -128,13 +124,6 @@ namespace EightBit {
int8_t m_displacement; 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() { int fetchExecute() {
M1() = true; M1() = true;
return execute(fetchByteExecute()); return execute(fetchByteExecute());
@ -299,18 +288,12 @@ namespace EightBit {
adc(hl, operand); 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) { void adjustHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
auto index = buildHalfCarryIndex(before, value, calculation); setFlag(HC, calculateHalfCarryAdd(before, value, calculation));
setFlag(HC, m_halfCarryTableAdd[index & 0x7]);
} }
void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) { void adjustHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
auto index = buildHalfCarryIndex(before, value, calculation); setFlag(HC, calculateHalfCarrySub(before, value, calculation));
setFlag(HC, m_halfCarryTableSub[index & 0x7]);
} }
void adjustOverflowAdd(uint8_t before, uint8_t value, uint8_t calculation) { void adjustOverflowAdd(uint8_t before, uint8_t value, uint8_t calculation) {
@ -362,7 +345,7 @@ namespace EightBit {
void jumpConditional(int condition); void jumpConditional(int condition);
void jumpConditionalFlag(int flag); void jumpConditionalFlag(int flag);
void call(); virtual void call() override;
void callConditional(int condition); void callConditional(int condition);
void callConditionalFlag(int flag); void callConditionalFlag(int flag);

View File

@ -5,7 +5,7 @@
// Half carry flag help from https://github.com/oubiwann/z80 // Half carry flag help from https://github.com/oubiwann/z80
EightBit::Z80::Z80(Memory& memory, InputOutput& ports) EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
: Processor(memory), : IntelProcessor(memory),
m_ports(ports), m_ports(ports),
m_registerSet(0), m_registerSet(0),
m_accumulatorFlagsSet(0), m_accumulatorFlagsSet(0),
@ -21,17 +21,16 @@ EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
m_prefixFD(false) { m_prefixFD(false) {
IX().word = 0xffff; IX().word = 0xffff;
IY().word = 0xffff; IY().word = 0xffff;
MEMPTR().word = 0;
} }
void EightBit::Z80::reset() { void EightBit::Z80::reset() {
Processor::reset(); IntelProcessor::reset();
IFF1() = IFF2() = false; IFF1() = IFF2() = false;
} }
void EightBit::Z80::initialise() { void EightBit::Z80::initialise() {
Processor::initialise(); IntelProcessor::initialise();
IM() = 0; IM() = 0;
@ -55,7 +54,6 @@ void EightBit::Z80::initialise() {
REFRESH() = 0x7f; REFRESH() = 0x7f;
IV() = 0xff; IV() = 0xff;
MEMPTR().word = 0;
m_prefixCB = false; m_prefixCB = false;
m_prefixDD = false; m_prefixDD = false;
@ -294,8 +292,7 @@ void EightBit::Z80::returnConditionalFlag(int flag) {
} }
void EightBit::Z80::call() { void EightBit::Z80::call() {
pushWord(pc); IntelProcessor::call();
pc = MEMPTR();
cycles += 7; cycles += 7;
} }

53
inc/IntelProcessor.h Normal file
View 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;
};
}

View File

@ -44,8 +44,6 @@ namespace EightBit {
static uint8_t promoteNibble(uint8_t value) { return value << 4; } static uint8_t promoteNibble(uint8_t value) { return value << 4; }
static uint8_t demoteNibble(uint8_t value) { return highNibble(value); } static uint8_t demoteNibble(uint8_t value) { return highNibble(value); }
Processor(Memory& memory);
const Memory& getMemory() const { return m_memory; } const Memory& getMemory() const { return m_memory; }
register16_t getProgramCounter() const { return pc; } register16_t getProgramCounter() const { return pc; }
@ -62,6 +60,8 @@ namespace EightBit {
void reset(); void reset();
protected: protected:
Processor(Memory& memory);
Memory& m_memory; Memory& m_memory;
int cycles; int cycles;
@ -71,12 +71,6 @@ namespace EightBit {
bool m_halted; bool m_halted;
void push(uint8_t value);
void pushWord(register16_t value);
uint8_t pop();
void popWord(register16_t& output);
uint8_t fetchByte() { uint8_t fetchByte() {
m_memory.ADDRESS().word = pc.word++; m_memory.ADDRESS().word = pc.word++;
return m_memory.reference(); return m_memory.reference();

View File

@ -143,6 +143,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\inc\EventArgs.h" /> <ClInclude Include="..\inc\EventArgs.h" />
<ClInclude Include="..\inc\IntelProcessor.h" />
<ClInclude Include="..\inc\Memory.h" /> <ClInclude Include="..\inc\Memory.h" />
<ClInclude Include="..\inc\Processor.h" /> <ClInclude Include="..\inc\Processor.h" />
<ClInclude Include="..\inc\Signal.h" /> <ClInclude Include="..\inc\Signal.h" />
@ -150,6 +151,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="EventArgs.cpp" /> <ClCompile Include="EventArgs.cpp" />
<ClCompile Include="IntelProcessor.cpp" />
<ClCompile Include="Memory.cpp" /> <ClCompile Include="Memory.cpp" />
<ClCompile Include="Processor.cpp" /> <ClCompile Include="Processor.cpp" />
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">

View File

@ -26,6 +26,9 @@
<ClInclude Include="..\inc\Signal.h"> <ClInclude Include="..\inc\Signal.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\inc\IntelProcessor.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">
@ -40,5 +43,8 @@
<ClCompile Include="Processor.cpp"> <ClCompile Include="Processor.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="IntelProcessor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

36
src/IntelProcessor.cpp Normal file
View 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();
}

View File

@ -17,23 +17,3 @@ void EightBit::Processor::initialise() {
sp.word = 0xffff; sp.word = 0xffff;
reset(); 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();
}