mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-07-29 06:24:23 +00:00
Tidy up register and static method access.
Signed-off-by: Adrian.Conlon <adrian.conlon@arup.com>
This commit is contained in:
@@ -79,39 +79,39 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void adjustReservedFlags() {
|
void adjustReservedFlags() {
|
||||||
AF().low &= ~(Bit5 | Bit3);
|
F() &= ~(Bit5 | Bit3);
|
||||||
AF().low |= Bit1;
|
F() |= Bit1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adjustSign(uint8_t& f, uint8_t value) { setFlag(f, SF, value & SF); }
|
static void adjustSign(uint8_t& f, uint8_t value) { setFlag(f, SF, value & SF); }
|
||||||
static void adjustZero(uint8_t& f, uint8_t value) { clearFlag(f, ZF, value); }
|
static void adjustZero(uint8_t& f, uint8_t value) { clearFlag(f, ZF, value); }
|
||||||
|
|
||||||
void adjustParity(uint8_t& f, uint8_t value) {
|
static void adjustParity(uint8_t& f, uint8_t value) {
|
||||||
static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
|
static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
|
||||||
auto set = (lookup[highNibble(value)] + lookup[lowNibble(value)]);
|
auto set = (lookup[highNibble(value)] + lookup[lowNibble(value)]);
|
||||||
clearFlag(f, PF, set % 2);
|
clearFlag(f, PF, set % 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustSZP(uint8_t& f, uint8_t value) {
|
static void adjustSZP(uint8_t& f, uint8_t value) {
|
||||||
adjustSign(f, value);
|
adjustSign(f, value);
|
||||||
adjustZero(f, value);
|
adjustZero(f, value);
|
||||||
adjustParity(f, value);
|
adjustParity(f, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustAuxiliaryCarryAdd(uint8_t& f, uint8_t value, int calculation) {
|
static void adjustAuxiliaryCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
||||||
setFlag(f, AC, calculateHalfCarryAdd(A(), value, calculation));
|
setFlag(f, AC, calculateHalfCarryAdd(before, value, calculation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustAuxiliaryCarrySub(uint8_t& f, uint8_t value, int calculation) {
|
static void adjustAuxiliaryCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
||||||
clearFlag(f, AC, calculateHalfCarrySub(A(), value, calculation));
|
clearFlag(f, AC, calculateHalfCarrySub(before, value, calculation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void postIncrement(uint8_t& f, uint8_t value) {
|
static void postIncrement(uint8_t& f, uint8_t value) {
|
||||||
adjustSZP(f, value);
|
adjustSZP(f, value);
|
||||||
clearFlag(f, AC, lowNibble(value));
|
clearFlag(f, AC, lowNibble(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void postDecrement(uint8_t& f, uint8_t value) {
|
static void postDecrement(uint8_t& f, uint8_t value) {
|
||||||
adjustSZP(f, value);
|
adjustSZP(f, value);
|
||||||
setFlag(f, AC, lowNibble(value) != Mask4);
|
setFlag(f, AC, lowNibble(value) != Mask4);
|
||||||
}
|
}
|
||||||
@@ -124,18 +124,20 @@ namespace EightBit {
|
|||||||
//
|
//
|
||||||
|
|
||||||
void compare(uint8_t value) {
|
void compare(uint8_t value) {
|
||||||
|
const auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
uint16_t subtraction = A() - value;
|
uint16_t subtraction = a - value;
|
||||||
adjustSZP(f, (uint8_t)subtraction);
|
adjustSZP(f, (uint8_t)subtraction);
|
||||||
adjustAuxiliaryCarrySub(f, value, subtraction);
|
adjustAuxiliaryCarrySub(f, a, value, subtraction);
|
||||||
setFlag(f, CF, subtraction & Bit8);
|
setFlag(f, CF, subtraction & Bit8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void anda(uint8_t value) {
|
void anda(uint8_t value) {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
setFlag(f, AC, (A() | value) & Bit3);
|
setFlag(f, AC, (a | value) & Bit3);
|
||||||
clearFlag(f, CF);
|
clearFlag(f, CF);
|
||||||
adjustSZP(f, A() &= value);
|
adjustSZP(f, a &= value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ora(uint8_t value) {
|
void ora(uint8_t value) {
|
||||||
@@ -151,13 +153,14 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add(uint8_t value, int carry = 0) {
|
void add(uint8_t value, int carry = 0) {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
register16_t sum;
|
register16_t sum;
|
||||||
sum.word = A() + value + carry;
|
sum.word = a + value + carry;
|
||||||
adjustAuxiliaryCarryAdd(f, value, sum.word);
|
adjustAuxiliaryCarryAdd(f, a, value, sum.word);
|
||||||
A() = sum.low;
|
a = sum.low;
|
||||||
setFlag(f, CF, sum.word & Bit8);
|
setFlag(f, CF, sum.word & Bit8);
|
||||||
adjustSZP(f, A());
|
adjustSZP(f, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc(uint8_t value) {
|
void adc(uint8_t value) {
|
||||||
@@ -172,13 +175,14 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sub(uint8_t value, int carry = 0) {
|
void sub(uint8_t value, int carry = 0) {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
register16_t difference;
|
register16_t difference;
|
||||||
difference.word = A() - value - carry;
|
difference.word = a - value - carry;
|
||||||
adjustAuxiliaryCarrySub(f, value, difference.word);
|
adjustAuxiliaryCarrySub(f, a, value, difference.word);
|
||||||
A() = difference.low;
|
a = difference.low;
|
||||||
setFlag(f, CF, difference.word & Bit8);
|
setFlag(f, CF, difference.word & Bit8);
|
||||||
adjustSZP(f, A());
|
adjustSZP(f, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbb(uint8_t value) {
|
void sbb(uint8_t value) {
|
||||||
@@ -335,21 +339,21 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void xhtl() {
|
void xhtl() {
|
||||||
auto tos = m_memory.getWord(sp.word);
|
auto tos = m_memory.getWord(SP().word);
|
||||||
m_memory.setWord(sp.word, HL());
|
m_memory.setWord(SP().word, HL());
|
||||||
HL() = tos;
|
HL() = tos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sphl() {
|
void sphl() {
|
||||||
sp = HL();
|
SP() = HL();
|
||||||
}
|
}
|
||||||
|
|
||||||
void lxi_sp() {
|
void lxi_sp() {
|
||||||
Processor::fetchWord(sp);
|
Processor::fetchWord(SP());
|
||||||
}
|
}
|
||||||
|
|
||||||
void inx_sp() { ++sp.word; }
|
void inx_sp() { ++SP().word; }
|
||||||
void dcx_sp() { --sp.word; }
|
void dcx_sp() { --SP().word; }
|
||||||
|
|
||||||
// jump
|
// jump
|
||||||
|
|
||||||
@@ -368,7 +372,7 @@ namespace EightBit {
|
|||||||
void jp() { jumpConditional(!(F() & SF)); }
|
void jp() { jumpConditional(!(F() & SF)); }
|
||||||
|
|
||||||
void pchl() {
|
void pchl() {
|
||||||
pc = HL();
|
PC() = HL();
|
||||||
}
|
}
|
||||||
|
|
||||||
// call
|
// call
|
||||||
@@ -488,7 +492,7 @@ namespace EightBit {
|
|||||||
void dad_b() { dad(BC().word); }
|
void dad_b() { dad(BC().word); }
|
||||||
void dad_d() { dad(DE().word); }
|
void dad_d() { dad(DE().word); }
|
||||||
void dad_h() { dad(HL().word); }
|
void dad_h() { dad(HL().word); }
|
||||||
void dad_sp() { dad(sp.word); }
|
void dad_sp() { dad(SP().word); }
|
||||||
|
|
||||||
// subtract
|
// subtract
|
||||||
|
|
||||||
@@ -593,32 +597,36 @@ namespace EightBit {
|
|||||||
// rotate
|
// rotate
|
||||||
|
|
||||||
void rlc() {
|
void rlc() {
|
||||||
auto carry = A() & Bit7;
|
auto& a = A();
|
||||||
A() <<= 1;
|
auto carry = a & Bit7;
|
||||||
carry ? A() |= Bit0 : A() &= ~Bit0;
|
a <<= 1;
|
||||||
|
carry ? a |= Bit0 : a &= ~Bit0;
|
||||||
setFlag(F(), CF, carry);
|
setFlag(F(), CF, carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rrc() {
|
void rrc() {
|
||||||
auto carry = A() & Bit0;
|
auto& a = A();
|
||||||
A() >>= 1;
|
auto carry = a & Bit0;
|
||||||
carry ? A() |= Bit7 : A() &= ~Bit7;
|
a >>= 1;
|
||||||
|
carry ? a |= Bit7 : a &= ~Bit7;
|
||||||
setFlag(F(), CF, carry);
|
setFlag(F(), CF, carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ral() {
|
void ral() {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
auto carry = A() & Bit7;
|
auto carry = a & Bit7;
|
||||||
A() <<= 1;
|
a <<= 1;
|
||||||
A() |= (f & CF);
|
a |= (f & CF);
|
||||||
setFlag(f, CF, carry);
|
setFlag(f, CF, carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rar() {
|
void rar() {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
auto carry = A() & 1;
|
auto carry = a & 1;
|
||||||
A() >>= 1;
|
a >>= 1;
|
||||||
A() |= (f & CF) << 7;
|
a |= (f & CF) << 7;
|
||||||
setFlag(f, CF, carry);
|
setFlag(f, CF, carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,13 +637,14 @@ namespace EightBit {
|
|||||||
void cmc() { clearFlag(F(), CF, F() & CF); }
|
void cmc() { clearFlag(F(), CF, F() & CF); }
|
||||||
|
|
||||||
void daa() {
|
void daa() {
|
||||||
|
const auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
auto carry = f & CF;
|
auto carry = f & CF;
|
||||||
uint8_t addition = 0;
|
uint8_t addition = 0;
|
||||||
if ((f & AC) || lowNibble(A()) > 9) {
|
if ((f & AC) || lowNibble(a) > 9) {
|
||||||
addition = 0x6;
|
addition = 0x6;
|
||||||
}
|
}
|
||||||
if ((f & CF) || highNibble(A()) > 9 || (highNibble(A()) >= 9 && lowNibble(A()) > 9)) {
|
if ((f & CF) || highNibble(a) > 9 || (highNibble(a) >= 9 && lowNibble(a) > 9)) {
|
||||||
addition |= 0x60;
|
addition |= 0x60;
|
||||||
carry = true;
|
carry = true;
|
||||||
}
|
}
|
||||||
@@ -655,6 +664,6 @@ namespace EightBit {
|
|||||||
|
|
||||||
void nop() {}
|
void nop() {}
|
||||||
|
|
||||||
void hlt() { m_halted = true; }
|
void hlt() { halt(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
@@ -13,8 +13,8 @@ EightBit::Disassembler::Disassembler() {
|
|||||||
|
|
||||||
std::string EightBit::Disassembler::state(Intel8080& cpu) {
|
std::string EightBit::Disassembler::state(Intel8080& cpu) {
|
||||||
|
|
||||||
auto pc = cpu.getProgramCounter();
|
auto pc = cpu.PC();
|
||||||
auto sp = cpu.getStackPointer();
|
auto sp = cpu.SP();
|
||||||
|
|
||||||
auto a = cpu.A();
|
auto a = cpu.A();
|
||||||
auto f = cpu.F();
|
auto f = cpu.F();
|
||||||
@@ -45,7 +45,7 @@ std::string EightBit::Disassembler::state(Intel8080& cpu) {
|
|||||||
std::string EightBit::Disassembler::disassemble(Intel8080& cpu) {
|
std::string EightBit::Disassembler::disassemble(Intel8080& cpu) {
|
||||||
|
|
||||||
const auto& memory = cpu.getMemory();
|
const auto& memory = cpu.getMemory();
|
||||||
auto pc = cpu.getProgramCounter();
|
auto pc = cpu.PC();
|
||||||
auto opcode = memory.peek(pc.word);
|
auto opcode = memory.peek(pc.word);
|
||||||
const auto& instruction = cpu.getInstructions()[opcode];
|
const auto& instruction = cpu.getInstructions()[opcode];
|
||||||
|
|
||||||
|
@@ -75,7 +75,7 @@ int EightBit::Intel8080::execute(uint8_t opcode) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
void EightBit::Intel8080::___() {
|
void EightBit::Intel8080::___() {
|
||||||
auto opcode = m_memory.get(pc.word - 1);
|
auto opcode = m_memory.get(PC().word - 1);
|
||||||
auto message = Disassembler::invalid(opcode);
|
auto message = Disassembler::invalid(opcode);
|
||||||
throw std::domain_error(message);
|
throw std::domain_error(message);
|
||||||
}
|
}
|
||||||
|
@@ -33,11 +33,11 @@ void Board::initialise() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_cpu.initialise();
|
m_cpu.initialise();
|
||||||
m_cpu.setProgramCounter(m_configuration.getStartAddress());
|
m_cpu.PC() = m_configuration.getStartAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080&) {
|
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080&) {
|
||||||
auto pc = m_cpu.getProgramCounter();
|
auto pc = m_cpu.PC();
|
||||||
switch (pc.word) {
|
switch (pc.word) {
|
||||||
case 0x0: // CP/M warm start
|
case 0x0: // CP/M warm start
|
||||||
m_cpu.halt();
|
m_cpu.halt();
|
||||||
@@ -69,7 +69,7 @@ void Board::bdos() {
|
|||||||
|
|
||||||
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpu) {
|
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpu) {
|
||||||
|
|
||||||
const auto pc = cpu.getProgramCounter();
|
const auto pc = m_cpu.PC();
|
||||||
|
|
||||||
m_profiler.addAddress(pc.word);
|
m_profiler.addAddress(pc.word);
|
||||||
m_profiler.addInstruction(m_memory.peek(pc.word));
|
m_profiler.addInstruction(m_memory.peek(pc.word));
|
||||||
|
@@ -98,7 +98,7 @@ namespace EightBit {
|
|||||||
register16_t& RP(int rp) {
|
register16_t& RP(int rp) {
|
||||||
switch (rp) {
|
switch (rp) {
|
||||||
case 3:
|
case 3:
|
||||||
return sp;
|
return SP();
|
||||||
default:
|
default:
|
||||||
return m_registers[rp];
|
return m_registers[rp];
|
||||||
}
|
}
|
||||||
@@ -113,21 +113,21 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
static void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
||||||
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustHalfCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
static void adjustHalfCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
||||||
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
|
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeCB(int x, int y, int z, int p, int q);
|
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 executeOther(int x, int y, int z, int p, int q);
|
||||||
|
|
||||||
void adjustZero(uint8_t& f, uint8_t value);
|
static void adjustZero(uint8_t& f, uint8_t value);
|
||||||
|
|
||||||
void postIncrement(uint8_t& f, uint8_t value);
|
static void postIncrement(uint8_t& f, uint8_t value);
|
||||||
void postDecrement(uint8_t& f, uint8_t value);
|
static void postDecrement(uint8_t& f, uint8_t value);
|
||||||
|
|
||||||
void reti();
|
void reti();
|
||||||
|
|
||||||
|
@@ -16,8 +16,8 @@ EightBit::Disassembler::Disassembler() {
|
|||||||
|
|
||||||
std::string EightBit::Disassembler::state(EightBit::LR35902& cpu) {
|
std::string EightBit::Disassembler::state(EightBit::LR35902& cpu) {
|
||||||
|
|
||||||
auto pc = cpu.getProgramCounter();
|
auto pc = cpu.PC();
|
||||||
auto sp = cpu.getStackPointer();
|
auto sp = cpu.SP();
|
||||||
|
|
||||||
auto a = cpu.A();
|
auto a = cpu.A();
|
||||||
auto f = cpu.F();
|
auto f = cpu.F();
|
||||||
@@ -142,7 +142,7 @@ std::string EightBit::Disassembler::alu(int which) {
|
|||||||
std::string EightBit::Disassembler::disassemble(LR35902& cpu) {
|
std::string EightBit::Disassembler::disassemble(LR35902& cpu) {
|
||||||
m_prefixCB = false;
|
m_prefixCB = false;
|
||||||
std::ostringstream output;
|
std::ostringstream output;
|
||||||
disassemble(output, cpu, cpu.getProgramCounter().word);
|
disassemble(output, cpu, cpu.PC().word);
|
||||||
return output.str();
|
return output.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ EightBit::LR35902::LR35902(Bus& memory)
|
|||||||
|
|
||||||
void EightBit::LR35902::reset() {
|
void EightBit::LR35902::reset() {
|
||||||
IntelProcessor::reset();
|
IntelProcessor::reset();
|
||||||
sp.word = 0xfffe;
|
SP().word = 0xfffe;
|
||||||
di();
|
di();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,7 +503,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 1: // GB: LD (nn),SP
|
case 1: // GB: LD (nn),SP
|
||||||
fetchWord();
|
fetchWord();
|
||||||
m_memory.setWord(MEMPTR().word, sp);
|
m_memory.setWord(MEMPTR().word, SP());
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
break;
|
break;
|
||||||
case 2: // GB: STOP
|
case 2: // GB: STOP
|
||||||
@@ -703,12 +703,13 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 5: { // GB: ADD SP,dd
|
case 5: { // GB: ADD SP,dd
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
auto before = sp;
|
auto before = SP();
|
||||||
auto value = fetchByte();
|
auto value = fetchByte();
|
||||||
sp.word += (int8_t)value;
|
auto result = SP().word + (int8_t)value;
|
||||||
|
SP().word = result;
|
||||||
clearFlag(f, ZF | NF);
|
clearFlag(f, ZF | NF);
|
||||||
setFlag(f, CF, sp.word & Bit16);
|
setFlag(f, CF, result & Bit16);
|
||||||
adjustHalfCarryAdd(f, before.high, value, sp.high);
|
adjustHalfCarryAdd(f, before.high, value, SP().high);
|
||||||
}
|
}
|
||||||
cycles += 4;
|
cycles += 4;
|
||||||
break;
|
break;
|
||||||
@@ -718,11 +719,12 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 7: { // GB: LD HL,SP + dd
|
case 7: { // GB: LD HL,SP + dd
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
auto before = sp;
|
auto before = HL();
|
||||||
auto value = fetchByte();
|
auto value = fetchByte();
|
||||||
HL().word = before.word + (int8_t)value;
|
auto result = SP().word + (int8_t)value;
|
||||||
|
HL().word = result;
|
||||||
clearFlag(f, ZF | NF);
|
clearFlag(f, ZF | NF);
|
||||||
setFlag(f, CF, HL().word & Bit16);
|
setFlag(f, CF, result & Bit16);
|
||||||
adjustHalfCarryAdd(f, before.high, value, HL().high);
|
adjustHalfCarryAdd(f, before.high, value, HL().high);
|
||||||
}
|
}
|
||||||
cycles += 3;
|
cycles += 3;
|
||||||
@@ -747,11 +749,11 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
|||||||
cycles += 4;
|
cycles += 4;
|
||||||
break;
|
break;
|
||||||
case 2: // JP HL
|
case 2: // JP HL
|
||||||
pc = HL();
|
PC() = HL();
|
||||||
cycles += 1;
|
cycles += 1;
|
||||||
break;
|
break;
|
||||||
case 3: // LD SP,HL
|
case 3: // LD SP,HL
|
||||||
sp = HL();
|
SP() = HL();
|
||||||
cycles += 2;
|
cycles += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -39,8 +39,8 @@ void Fuse::TestRunner::initialiseRegisters() {
|
|||||||
m_cpu.IX() = inputRegisters[Fuse::RegisterState::IX];
|
m_cpu.IX() = inputRegisters[Fuse::RegisterState::IX];
|
||||||
m_cpu.IY() = inputRegisters[Fuse::RegisterState::IY];
|
m_cpu.IY() = inputRegisters[Fuse::RegisterState::IY];
|
||||||
|
|
||||||
m_cpu.setStackPointer(inputRegisters[Fuse::RegisterState::SP]);
|
m_cpu.SP() = inputRegisters[Fuse::RegisterState::SP];
|
||||||
m_cpu.setProgramCounter(inputRegisters[Fuse::RegisterState::PC]);
|
m_cpu.PC() = inputRegisters[Fuse::RegisterState::PC];
|
||||||
|
|
||||||
m_cpu.MEMPTR() = inputRegisters[Fuse::RegisterState::MEMPTR];
|
m_cpu.MEMPTR() = inputRegisters[Fuse::RegisterState::MEMPTR];
|
||||||
|
|
||||||
@@ -115,8 +115,8 @@ void Fuse::TestRunner::checkregisters() {
|
|||||||
auto ix = m_cpu.IX().word == expectedRegisters[Fuse::RegisterState::IX].word;
|
auto ix = m_cpu.IX().word == expectedRegisters[Fuse::RegisterState::IX].word;
|
||||||
auto iy = m_cpu.IY().word == expectedRegisters[Fuse::RegisterState::IY].word;
|
auto iy = m_cpu.IY().word == expectedRegisters[Fuse::RegisterState::IY].word;
|
||||||
|
|
||||||
auto sp = m_cpu.getStackPointer().word == expectedRegisters[Fuse::RegisterState::SP].word;
|
auto sp = m_cpu.SP().word == expectedRegisters[Fuse::RegisterState::SP].word;
|
||||||
auto pc = m_cpu.getProgramCounter().word == expectedRegisters[Fuse::RegisterState::PC].word;
|
auto pc = m_cpu.PC().word == expectedRegisters[Fuse::RegisterState::PC].word;
|
||||||
|
|
||||||
auto memptr = m_cpu.MEMPTR().word == expectedRegisters[Fuse::RegisterState::MEMPTR].word;
|
auto memptr = m_cpu.MEMPTR().word == expectedRegisters[Fuse::RegisterState::MEMPTR].word;
|
||||||
|
|
||||||
@@ -194,13 +194,13 @@ void Fuse::TestRunner::checkregisters() {
|
|||||||
|
|
||||||
if (!sp) {
|
if (!sp) {
|
||||||
auto expectedWord = expectedRegisters[Fuse::RegisterState::SP];
|
auto expectedWord = expectedRegisters[Fuse::RegisterState::SP];
|
||||||
auto actualWord = m_cpu.getStackPointer();
|
auto actualWord = m_cpu.SP();
|
||||||
dumpDifference("SPH", "SPL", actualWord, expectedWord);
|
dumpDifference("SPH", "SPL", actualWord, expectedWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pc) {
|
if (!pc) {
|
||||||
auto expectedWord = expectedRegisters[Fuse::RegisterState::PC];
|
auto expectedWord = expectedRegisters[Fuse::RegisterState::PC];
|
||||||
auto actualWord = m_cpu.getProgramCounter();
|
auto actualWord = m_cpu.PC();
|
||||||
dumpDifference("PCH", "PCL", actualWord, expectedWord);
|
dumpDifference("PCH", "PCL", actualWord, expectedWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@ namespace EightBit {
|
|||||||
Disassembler();
|
Disassembler();
|
||||||
|
|
||||||
static std::string state(Z80& cpu);
|
static std::string state(Z80& cpu);
|
||||||
std::string disassemble(const Z80& cpu);
|
std::string disassemble(Z80& cpu);
|
||||||
|
|
||||||
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
||||||
static std::string flags(uint8_t value);
|
static std::string flags(uint8_t value);
|
||||||
|
@@ -37,8 +37,6 @@ namespace EightBit {
|
|||||||
int execute(uint8_t opcode);
|
int execute(uint8_t opcode);
|
||||||
int step();
|
int step();
|
||||||
|
|
||||||
bool getM1() const { return m1; }
|
|
||||||
|
|
||||||
// Mutable access to processor!!
|
// Mutable access to processor!!
|
||||||
|
|
||||||
virtual register16_t& AF() override {
|
virtual register16_t& AF() override {
|
||||||
@@ -181,7 +179,7 @@ namespace EightBit {
|
|||||||
register16_t& RP(int rp) {
|
register16_t& RP(int rp) {
|
||||||
switch (rp) {
|
switch (rp) {
|
||||||
case 3:
|
case 3:
|
||||||
return sp;
|
return SP();
|
||||||
case HL_IDX:
|
case HL_IDX:
|
||||||
return HL2();
|
return HL2();
|
||||||
default:
|
default:
|
||||||
@@ -225,28 +223,28 @@ namespace EightBit {
|
|||||||
adc(hl, operand);
|
adc(hl, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
static void adjustHalfCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
||||||
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
setFlag(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustHalfCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
static void adjustHalfCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
|
||||||
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
|
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustOverflowAdd(uint8_t& f, uint8_t before, uint8_t value, uint8_t calculation) {
|
static void adjustOverflowAdd(uint8_t& f, uint8_t before, uint8_t value, uint8_t calculation) {
|
||||||
adjustOverflowAdd(f, before & SF, value & SF, calculation & SF);
|
adjustOverflowAdd(f, before & SF, value & SF, calculation & SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustOverflowAdd(uint8_t& f, int beforeNegative, int valueNegative, int afterNegative) {
|
static void adjustOverflowAdd(uint8_t& f, int beforeNegative, int valueNegative, int afterNegative) {
|
||||||
auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
|
auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
|
||||||
setFlag(f, VF, overflow);
|
setFlag(f, VF, overflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustOverflowSub(uint8_t& f, uint8_t before, uint8_t value, uint8_t calculation) {
|
static void adjustOverflowSub(uint8_t& f, uint8_t before, uint8_t value, uint8_t calculation) {
|
||||||
adjustOverflowSub(f, before & SF, value & SF, calculation & SF);
|
adjustOverflowSub(f, before & SF, value & SF, calculation & SF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustOverflowSub(uint8_t& f, int beforeNegative, int valueNegative, int afterNegative) {
|
static void adjustOverflowSub(uint8_t& f, int beforeNegative, int valueNegative, int afterNegative) {
|
||||||
auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
|
auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
|
||||||
setFlag(f, VF, overflow);
|
setFlag(f, VF, overflow);
|
||||||
}
|
}
|
||||||
@@ -298,9 +296,9 @@ namespace EightBit {
|
|||||||
uint8_t& sll(uint8_t& operand);
|
uint8_t& sll(uint8_t& operand);
|
||||||
uint8_t& srl(uint8_t& operand);
|
uint8_t& srl(uint8_t& operand);
|
||||||
|
|
||||||
void bit(int n, uint8_t& operand);
|
uint8_t& bit(int n, uint8_t& operand);
|
||||||
void res(int n, uint8_t& operand);
|
uint8_t& res(int n, uint8_t& operand);
|
||||||
void set(int nit, uint8_t& operand);
|
uint8_t& set(int nit, uint8_t& operand);
|
||||||
|
|
||||||
void daa();
|
void daa();
|
||||||
|
|
||||||
|
@@ -15,8 +15,8 @@ EightBit::Disassembler::Disassembler() {
|
|||||||
|
|
||||||
std::string EightBit::Disassembler::state(Z80& cpu) {
|
std::string EightBit::Disassembler::state(Z80& cpu) {
|
||||||
|
|
||||||
auto pc = cpu.getProgramCounter();
|
auto pc = cpu.PC();
|
||||||
auto sp = cpu.getStackPointer();
|
auto sp = cpu.SP();
|
||||||
|
|
||||||
auto a = cpu.A();
|
auto a = cpu.A();
|
||||||
auto f = cpu.F();
|
auto f = cpu.F();
|
||||||
@@ -169,10 +169,10 @@ std::string EightBit::Disassembler::alu(int which) {
|
|||||||
throw std::logic_error("Unhandled alu operation");
|
throw std::logic_error("Unhandled alu operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EightBit::Disassembler::disassemble(const Z80& cpu) {
|
std::string EightBit::Disassembler::disassemble(Z80& cpu) {
|
||||||
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
||||||
std::ostringstream output;
|
std::ostringstream output;
|
||||||
disassemble(output, cpu, cpu.getProgramCounter().word);
|
disassemble(output, cpu, cpu.PC().word);
|
||||||
return output.str();
|
return output.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -86,9 +86,9 @@ int EightBit::Z80::interrupt(bool maskable, uint8_t value) {
|
|||||||
cycles += 13;
|
cycles += 13;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
pushWord(pc);
|
pushWord(PC());
|
||||||
pc.low = value;
|
PC().low = value;
|
||||||
pc.high = IV();
|
PC().high = IV();
|
||||||
cycles += 19;
|
cycles += 19;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -502,23 +502,26 @@ uint8_t& EightBit::Z80::srl(uint8_t& operand) {
|
|||||||
|
|
||||||
#pragma region BIT/SET/RES
|
#pragma region BIT/SET/RES
|
||||||
|
|
||||||
void EightBit::Z80::bit(int n, uint8_t& operand) {
|
uint8_t& EightBit::Z80::bit(int n, uint8_t& operand) {
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
auto carry = f & CF;
|
auto carry = f & CF;
|
||||||
uint8_t discarded = operand;
|
uint8_t discarded = operand;
|
||||||
andr(discarded, 1 << n);
|
andr(discarded, 1 << n);
|
||||||
clearFlag(f, PF, discarded);
|
clearFlag(f, PF, discarded);
|
||||||
setFlag(f, CF, carry);
|
setFlag(f, CF, carry);
|
||||||
|
return operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Z80::res(int n, uint8_t& operand) {
|
uint8_t& EightBit::Z80::res(int n, uint8_t& operand) {
|
||||||
auto bit = 1 << n;
|
auto bit = 1 << n;
|
||||||
operand &= ~bit;
|
operand &= ~bit;
|
||||||
|
return operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Z80::set(int n, uint8_t& operand) {
|
uint8_t& EightBit::Z80::set(int n, uint8_t& operand) {
|
||||||
auto bit = 1 << n;
|
auto bit = 1 << n;
|
||||||
operand |= bit;
|
operand |= bit;
|
||||||
|
return operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion BIT/SET/RES
|
#pragma endregion BIT/SET/RES
|
||||||
@@ -526,22 +529,24 @@ void EightBit::Z80::set(int n, uint8_t& operand) {
|
|||||||
#pragma region Miscellaneous instructions
|
#pragma region Miscellaneous instructions
|
||||||
|
|
||||||
void EightBit::Z80::neg() {
|
void EightBit::Z80::neg() {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
auto original = A();
|
auto original = a;
|
||||||
A() = 0;
|
a = 0;
|
||||||
sub(A(), original);
|
sub(a, original);
|
||||||
setFlag(f, PF, original == Bit7);
|
setFlag(f, PF, original == Bit7);
|
||||||
setFlag(f, CF, original);
|
setFlag(f, CF, original);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Z80::daa() {
|
void EightBit::Z80::daa() {
|
||||||
|
|
||||||
|
auto& acc = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
|
|
||||||
uint8_t a = A();
|
auto a = acc;
|
||||||
|
|
||||||
auto lowAdjust = (f & HC) | (lowNibble(A()) > 9);
|
auto lowAdjust = (f & HC) | (lowNibble(acc) > 9);
|
||||||
auto highAdjust = (f & CF) | (A() > 0x99);
|
auto highAdjust = (f & CF) | (acc > 0x99);
|
||||||
|
|
||||||
if (f & NF) {
|
if (f & NF) {
|
||||||
if (lowAdjust)
|
if (lowAdjust)
|
||||||
@@ -555,16 +560,17 @@ void EightBit::Z80::daa() {
|
|||||||
a += 0x60;
|
a += 0x60;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = (f & (CF | NF)) | (A() > 0x99) | ((A() ^ a) & HC);
|
f = (f & (CF | NF)) | (acc > 0x99) | ((acc ^ a) & HC);
|
||||||
|
|
||||||
adjustSZPXY(f, a);
|
adjustSZPXY(f, a);
|
||||||
|
|
||||||
A() = a;
|
acc = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Z80::cpl() {
|
void EightBit::Z80::cpl() {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
A() = ~A();
|
a = ~a;
|
||||||
adjustXY(f, A());
|
adjustXY(f, A());
|
||||||
setFlag(f, HC | NF);
|
setFlag(f, HC | NF);
|
||||||
}
|
}
|
||||||
@@ -586,7 +592,7 @@ void EightBit::Z80::ccf() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Z80::xhtl(register16_t& operand) {
|
void EightBit::Z80::xhtl(register16_t& operand) {
|
||||||
m_memory.ADDRESS() = sp;
|
m_memory.ADDRESS() = SP();
|
||||||
MEMPTR().low = m_memory.reference();
|
MEMPTR().low = m_memory.reference();
|
||||||
m_memory.reference() = operand.low;
|
m_memory.reference() = operand.low;
|
||||||
operand.low = MEMPTR().low;
|
operand.low = MEMPTR().low;
|
||||||
@@ -608,17 +614,18 @@ void EightBit::Z80::xhtl() {
|
|||||||
|
|
||||||
void EightBit::Z80::blockCompare() {
|
void EightBit::Z80::blockCompare() {
|
||||||
|
|
||||||
|
const auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
|
|
||||||
m_memory.ADDRESS() = HL();
|
m_memory.ADDRESS() = HL();
|
||||||
|
|
||||||
auto value = m_memory.reference();
|
auto value = m_memory.reference();
|
||||||
uint8_t result = A() - value;
|
uint8_t result = a - value;
|
||||||
|
|
||||||
setFlag(f, PF, --BC().word);
|
setFlag(f, PF, --BC().word);
|
||||||
|
|
||||||
adjustSZ(f, result);
|
adjustSZ(f, result);
|
||||||
adjustHalfCarrySub(f, A(), value, result);
|
adjustHalfCarrySub(f, a, value, result);
|
||||||
setFlag(f, NF);
|
setFlag(f, NF);
|
||||||
|
|
||||||
if (f & HC)
|
if (f & HC)
|
||||||
@@ -642,7 +649,7 @@ void EightBit::Z80::cpd() {
|
|||||||
|
|
||||||
bool EightBit::Z80::cpir() {
|
bool EightBit::Z80::cpir() {
|
||||||
cpi();
|
cpi();
|
||||||
MEMPTR().word = pc.word;
|
MEMPTR() = PC();
|
||||||
auto again = (F() & PF) && !(F() & ZF); // See CPI
|
auto again = (F() & PF) && !(F() & ZF); // See CPI
|
||||||
if (again)
|
if (again)
|
||||||
MEMPTR().word--;
|
MEMPTR().word--;
|
||||||
@@ -651,7 +658,7 @@ bool EightBit::Z80::cpir() {
|
|||||||
|
|
||||||
bool EightBit::Z80::cpdr() {
|
bool EightBit::Z80::cpdr() {
|
||||||
cpd();
|
cpd();
|
||||||
MEMPTR().word = pc.word - 1;
|
MEMPTR().word = PC().word - 1;
|
||||||
auto again = (F() & PF) && !(F() & ZF); // See CPD
|
auto again = (F() & PF) && !(F() & ZF); // See CPD
|
||||||
if (!again)
|
if (!again)
|
||||||
MEMPTR().word--;
|
MEMPTR().word--;
|
||||||
@@ -691,7 +698,7 @@ bool EightBit::Z80::ldir() {
|
|||||||
ldi();
|
ldi();
|
||||||
auto again = (F() & PF) != 0;
|
auto again = (F() & PF) != 0;
|
||||||
if (again) // See LDI
|
if (again) // See LDI
|
||||||
MEMPTR().word = pc.word - 1;
|
MEMPTR().word = PC().word - 1;
|
||||||
return again;
|
return again;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,7 +706,7 @@ bool EightBit::Z80::lddr() {
|
|||||||
ldd();
|
ldd();
|
||||||
auto again = (F() & PF) != 0;
|
auto again = (F() & PF) != 0;
|
||||||
if (again) // See LDR
|
if (again) // See LDR
|
||||||
MEMPTR().word = pc.word - 1;
|
MEMPTR().word = PC().word - 1;
|
||||||
return again;
|
return again;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,22 +792,24 @@ bool EightBit::Z80::otdr() {
|
|||||||
#pragma region Nibble rotation
|
#pragma region Nibble rotation
|
||||||
|
|
||||||
void EightBit::Z80::rrd() {
|
void EightBit::Z80::rrd() {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
MEMPTR() = HL();
|
MEMPTR() = HL();
|
||||||
auto memory = memptrReference();
|
auto memory = memptrReference();
|
||||||
m_memory.reference() = promoteNibble(A()) | highNibble(memory);
|
m_memory.reference() = promoteNibble(a) | highNibble(memory);
|
||||||
A() = (A() & 0xf0) | lowNibble(memory);
|
a = (a & 0xf0) | lowNibble(memory);
|
||||||
adjustSZPXY(f, A());
|
adjustSZPXY(f, A());
|
||||||
clearFlag(f, NF | HC);
|
clearFlag(f, NF | HC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Z80::rld() {
|
void EightBit::Z80::rld() {
|
||||||
|
auto& a = A();
|
||||||
auto& f = F();
|
auto& f = F();
|
||||||
MEMPTR() = HL();
|
MEMPTR() = HL();
|
||||||
auto memory = memptrReference();
|
auto memory = memptrReference();
|
||||||
m_memory.reference() = promoteNibble(memory) | lowNibble(A());
|
m_memory.reference() = promoteNibble(memory) | lowNibble(a);
|
||||||
A() = (A() & 0xf0) | highNibble(memory);
|
a = (a & 0xf0) | highNibble(memory);
|
||||||
adjustSZPXY(f, A());
|
adjustSZPXY(f, a);
|
||||||
clearFlag(f, NF | HC);
|
clearFlag(f, NF | HC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,7 +824,7 @@ int EightBit::Z80::step() {
|
|||||||
|
|
||||||
int EightBit::Z80::execute(uint8_t opcode) {
|
int EightBit::Z80::execute(uint8_t opcode) {
|
||||||
|
|
||||||
if (!getM1())
|
if (!M1())
|
||||||
throw std::logic_error("M1 cannot be high");
|
throw std::logic_error("M1 cannot be high");
|
||||||
|
|
||||||
auto x = (opcode & 0b11000000) >> 6;
|
auto x = (opcode & 0b11000000) >> 6;
|
||||||
@@ -887,8 +896,7 @@ void EightBit::Z80::executeCB(int x, int y, int z, int p, int q) {
|
|||||||
adjustXY(f, MEMPTR().high);
|
adjustXY(f, MEMPTR().high);
|
||||||
cycles += 20;
|
cycles += 20;
|
||||||
} else {
|
} else {
|
||||||
auto operand = R(z);
|
auto operand = bit(y, R(z));
|
||||||
bit(y, operand);
|
|
||||||
cycles += 8;
|
cycles += 8;
|
||||||
if (z == 6) {
|
if (z == 6) {
|
||||||
adjustXY(f, MEMPTR().high);
|
adjustXY(f, MEMPTR().high);
|
||||||
@@ -900,8 +908,7 @@ void EightBit::Z80::executeCB(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 2: // RES y, r[z]
|
case 2: // RES y, r[z]
|
||||||
if (m_displaced) {
|
if (m_displaced) {
|
||||||
res(y, DISPLACED());
|
R2(z) = res(y, DISPLACED());
|
||||||
R2(z) = DISPLACED();
|
|
||||||
cycles += 23;
|
cycles += 23;
|
||||||
} else {
|
} else {
|
||||||
res(y, R(z));
|
res(y, R(z));
|
||||||
@@ -912,8 +919,7 @@ void EightBit::Z80::executeCB(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 3: // SET y, r[z]
|
case 3: // SET y, r[z]
|
||||||
if (m_displaced) {
|
if (m_displaced) {
|
||||||
set(y, DISPLACED());
|
R2(z) = set(y, DISPLACED());
|
||||||
R2(z) = DISPLACED();
|
|
||||||
cycles += 23;
|
cycles += 23;
|
||||||
} else {
|
} else {
|
||||||
set(y, R(z));
|
set(y, R(z));
|
||||||
@@ -1065,13 +1071,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 6: // LDIR
|
case 6: // LDIR
|
||||||
if (ldir()) {
|
if (ldir()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7: // LDDR
|
case 7: // LDDR
|
||||||
if (lddr()) {
|
if (lddr()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1087,13 +1093,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 6: // CPIR
|
case 6: // CPIR
|
||||||
if (cpir()) {
|
if (cpir()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7: // CPDR
|
case 7: // CPDR
|
||||||
if (cpdr()) {
|
if (cpdr()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1109,13 +1115,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 6: // INIR
|
case 6: // INIR
|
||||||
if (inir()) {
|
if (inir()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7: // INDR
|
case 7: // INDR
|
||||||
if (indr()) {
|
if (indr()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1131,13 +1137,13 @@ void EightBit::Z80::executeED(int x, int y, int z, int p, int q) {
|
|||||||
break;
|
break;
|
||||||
case 6: // OTIR
|
case 6: // OTIR
|
||||||
if (otir()) {
|
if (otir()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7: // OTDR
|
case 7: // OTDR
|
||||||
if (otdr()) {
|
if (otdr()) {
|
||||||
pc.word -= 2;
|
PC().word -= 2;
|
||||||
cycles += 5;
|
cycles += 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1394,11 +1400,11 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
|
|||||||
cycles += 4;
|
cycles += 4;
|
||||||
break;
|
break;
|
||||||
case 2: // JP HL
|
case 2: // JP HL
|
||||||
pc = HL2();
|
PC() = HL2();
|
||||||
cycles += 4;
|
cycles += 4;
|
||||||
break;
|
break;
|
||||||
case 3: // LD SP,HL
|
case 3: // LD SP,HL
|
||||||
sp = HL2();
|
SP() = HL2();
|
||||||
cycles += 4;
|
cycles += 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -32,11 +32,11 @@ void Board::initialise() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_cpu.initialise();
|
m_cpu.initialise();
|
||||||
m_cpu.setProgramCounter(m_configuration.getStartAddress());
|
m_cpu.PC() = m_configuration.getStartAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Z80&) {
|
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Z80&) {
|
||||||
auto pc = m_cpu.getProgramCounter();
|
auto pc = m_cpu.PC();
|
||||||
switch (pc.word) {
|
switch (pc.word) {
|
||||||
case 0x0: // CP/M warm start
|
case 0x0: // CP/M warm start
|
||||||
m_cpu.halt();
|
m_cpu.halt();
|
||||||
@@ -68,7 +68,7 @@ void Board::bdos() {
|
|||||||
|
|
||||||
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpu) {
|
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Z80& cpu) {
|
||||||
|
|
||||||
const auto pc = cpu.getProgramCounter();
|
const auto pc = m_cpu.PC();
|
||||||
|
|
||||||
m_profiler.addAddress(pc.word);
|
m_profiler.addAddress(pc.word);
|
||||||
m_profiler.addInstruction(m_memory.peek(pc.word));
|
m_profiler.addInstruction(m_memory.peek(pc.word));
|
||||||
@@ -79,6 +79,6 @@ void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Z80& cpu) {
|
|||||||
std::cerr
|
std::cerr
|
||||||
<< EightBit::Disassembler::state(m_cpu)
|
<< EightBit::Disassembler::state(m_cpu)
|
||||||
<< "\t"
|
<< "\t"
|
||||||
<< m_disassembler.disassemble(cpu)
|
<< m_disassembler.disassemble(m_cpu)
|
||||||
<< '\n';
|
<< '\n';
|
||||||
}
|
}
|
||||||
|
@@ -40,25 +40,24 @@ namespace EightBit {
|
|||||||
static void clearFlag(uint8_t& f, int flag, uint32_t condition) { clearFlag(f, flag, condition != 0); }
|
static void clearFlag(uint8_t& f, int flag, uint32_t condition) { clearFlag(f, flag, condition != 0); }
|
||||||
static void clearFlag(uint8_t& f, int flag, bool condition) { condition ? clearFlag(f, flag) : setFlag(f, flag); }
|
static void clearFlag(uint8_t& f, int flag, bool condition) { condition ? clearFlag(f, flag) : setFlag(f, flag); }
|
||||||
|
|
||||||
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
|
static int buildHalfCarryIndex(uint8_t before, uint8_t value, int calculation) {
|
||||||
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);
|
return ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool calculateHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
|
static bool calculateHalfCarryAdd(uint8_t before, uint8_t value, int calculation) {
|
||||||
|
static std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
|
||||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||||
return m_halfCarryTableAdd[index & Mask3];
|
return m_halfCarryTableAdd[index & Mask3];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool calculateHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
static bool calculateHalfCarrySub(uint8_t before, uint8_t value, int calculation) {
|
||||||
|
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
|
||||||
auto index = buildHalfCarryIndex(before, value, calculation);
|
auto index = buildHalfCarryIndex(before, value, calculation);
|
||||||
return m_halfCarryTableSub[index & Mask3];
|
return m_halfCarryTableSub[index & Mask3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void push(uint8_t value) {
|
void push(uint8_t value) {
|
||||||
m_memory.ADDRESS().word = --sp.word;
|
m_memory.ADDRESS().word = --SP().word;
|
||||||
m_memory.reference() = value;
|
m_memory.reference() = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pop() {
|
uint8_t pop() {
|
||||||
m_memory.ADDRESS().word = sp.word++;
|
m_memory.ADDRESS().word = SP().word++;
|
||||||
return m_memory.reference();
|
return m_memory.reference();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,11 +103,11 @@ namespace EightBit {
|
|||||||
//
|
//
|
||||||
|
|
||||||
void jump() {
|
void jump() {
|
||||||
pc = MEMPTR();
|
PC() = MEMPTR();
|
||||||
}
|
}
|
||||||
|
|
||||||
void call() {
|
void call() {
|
||||||
pushWord(pc);
|
pushWord(PC());
|
||||||
jump();
|
jump();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +143,7 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void jr(int8_t offset) {
|
void jr(int8_t offset) {
|
||||||
MEMPTR().word = pc.word + offset;
|
MEMPTR().word = PC().word + offset;
|
||||||
jump();
|
jump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,14 +46,11 @@ namespace EightBit {
|
|||||||
|
|
||||||
const Memory& getMemory() const { return m_memory; }
|
const Memory& getMemory() const { return m_memory; }
|
||||||
|
|
||||||
register16_t getProgramCounter() const { return pc; }
|
register16_t& PC() { return pc; }
|
||||||
void setProgramCounter(register16_t value) { pc = value; }
|
register16_t& SP() { return sp; }
|
||||||
|
|
||||||
register16_t getStackPointer() const { return sp; }
|
|
||||||
void setStackPointer(register16_t value) { sp = value; }
|
|
||||||
|
|
||||||
bool isHalted() const { return m_halted; }
|
bool isHalted() const { return m_halted; }
|
||||||
void halt() { --pc.word; m_halted = true; }
|
void halt() { --PC().word; m_halted = true; }
|
||||||
|
|
||||||
virtual void initialise();
|
virtual void initialise();
|
||||||
|
|
||||||
@@ -63,16 +60,10 @@ namespace EightBit {
|
|||||||
Processor(Memory& memory);
|
Processor(Memory& memory);
|
||||||
|
|
||||||
Memory& m_memory;
|
Memory& m_memory;
|
||||||
|
|
||||||
int cycles;
|
int cycles;
|
||||||
|
|
||||||
register16_t pc;
|
|
||||||
register16_t sp;
|
|
||||||
|
|
||||||
bool m_halted;
|
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,5 +71,10 @@ namespace EightBit {
|
|||||||
output.low = fetchByte();
|
output.low = fetchByte();
|
||||||
output.high = fetchByte();
|
output.high = fetchByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
register16_t pc;
|
||||||
|
register16_t sp;
|
||||||
|
bool m_halted;
|
||||||
};
|
};
|
||||||
}
|
}
|
@@ -5,15 +5,15 @@ EightBit::Processor::Processor(Memory& memory)
|
|||||||
: m_memory(memory),
|
: m_memory(memory),
|
||||||
cycles(0),
|
cycles(0),
|
||||||
m_halted(false) {
|
m_halted(false) {
|
||||||
sp.word = 0xffff;
|
SP().word = 0xffff;
|
||||||
pc.word = 0;
|
PC().word = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Processor::reset() {
|
void EightBit::Processor::reset() {
|
||||||
pc.word = 0;
|
PC().word = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Processor::initialise() {
|
void EightBit::Processor::initialise() {
|
||||||
sp.word = 0xffff;
|
SP().word = 0xffff;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user