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