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
#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);
}

View File

@ -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),

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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
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 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();

View File

@ -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">

View File

@ -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
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;
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();
}