Further work on uniting the 8080 family processor family.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon committed 2017-06-11 21:08:40 +01:00
1 parent 627e41bf35
commit 0291970427
8 files changed
+273 -420

No files matched your search

+39 -82
View File
@@ -50,12 +50,9 @@ namespace EightBit {
return m_interrupt; return m_interrupt;
} }
void disableInterrupts() { m_interrupt = false; }
void enableInterrupts() { m_interrupt = true; }
int interrupt(uint8_t value) { int interrupt(uint8_t value) {
if (isInterruptable()) { if (isInterruptable()) {
disableInterrupts(); di();
return execute(value); return execute(value);
} }
return 0; return 0;
@@ -133,42 +130,6 @@ namespace EightBit {
F().C = subtraction > 0xff; F().C = subtraction > 0xff;
} }
void callAddress(uint16_t address) {
register16_t saved = pc;
saved.word += 2;
pushWord(saved);
pc.word = address;
}
void restart(uint8_t position) {
uint16_t address = position << 3;
pushWord(pc);
pc.word = address;
}
void jmpConditional(int conditional) {
fetchWord();
if (conditional)
pc = MEMPTR();
}
void callConditional(int condition) {
if (condition) {
call();
cycles += 6;
}
else {
pc.word += 2;
}
}
void returnConditional(int condition) {
if (condition) {
ret();
cycles += 6;
}
}
void anda(uint8_t value) { void anda(uint8_t value) {
F().AC = (((A() | value) & 0x8) != 0); F().AC = (((A() | value) & 0x8) != 0);
F().C = false; F().C = false;
@@ -391,19 +352,19 @@ namespace EightBit {
// jump // jump
void jmp() { jmpConditional(true); } void jmp() { jumpConditional(true); }
void jc() { jmpConditional(F().C); } void jc() { jumpConditional(F().C); }
void jnc() { jmpConditional(!F().C); } void jnc() { jumpConditional(!F().C); }
void jz() { jmpConditional(F().Z); } void jz() { jumpConditional(F().Z); }
void jnz() { jmpConditional(!F().Z); } void jnz() { jumpConditional(!F().Z); }
void jpe() { jmpConditional(F().P); } void jpe() { jumpConditional(F().P); }
void jpo() { jmpConditional(!F().P); } void jpo() { jumpConditional(!F().P); }
void jm() { jmpConditional(F().S); } void jm() { jumpConditional(F().S); }
void jp() { jmpConditional(!F().S); } void jp() { jumpConditional(!F().S); }
void pchl() { void pchl() {
pc = HL(); pc = HL();
@@ -411,51 +372,47 @@ namespace EightBit {
// call // call
virtual void call() override { void callDirect() {
auto destination = m_memory.getWord(pc.word); fetchWord();
callAddress(destination.word); call();
} }
void cc() { callConditional(F().C); } void cc() { if (callConditional(F().C)) cycles += 6; }
void cnc() { callConditional(!F().C); } void cnc() { if (callConditional(!F().C)) cycles += 6; }
void cpe() { callConditional(F().P); } void cpe() { if (callConditional(F().P)) cycles += 6; }
void cpo() { callConditional(!F().P); } void cpo() { if (callConditional(!F().P)) cycles += 6; }
void cz() { callConditional(F().Z); } void cz() { if (callConditional(F().Z)) cycles += 6; }
void cnz() { callConditional(!F().Z); } void cnz() { if (callConditional(!F().Z)) cycles += 6; }
void cm() { callConditional(F().S); } void cm() { if (callConditional(F().S)) cycles += 6; }
void cp() { callConditional(!F().S); } void cp() { if (callConditional(!F().S)) cycles += 6; }
// return // return
void ret() { void rc() { if (returnConditional(F().C)) cycles += 6; }
popWord(pc); void rnc() { if (returnConditional(!F().C)) cycles += 6; }
}
void rc() { returnConditional(F().C); } void rz() { if (returnConditional(F().Z)) cycles += 6; }
void rnc() { returnConditional(!F().C); } void rnz() { if (returnConditional(!F().Z)) cycles += 6; }
void rz() { returnConditional(F().Z); } void rpe() { if (returnConditional(F().P)) cycles += 6; }
void rnz() { returnConditional(!F().Z); } void rpo() { if (returnConditional(!F().P)) cycles += 6; }
void rpe() { returnConditional(F().P); } void rm() { if (returnConditional(F().S)) cycles += 6; }
void rpo() { returnConditional(!F().P); } void rp() { if (returnConditional(!F().S)) cycles += 6; }
void rm() { returnConditional(F().S); }
void rp() { returnConditional(!F().S); }
// restart // restart
void rst_0() { restart(0); } void rst_0() { restart(0 << 3); }
void rst_1() { restart(1); } void rst_1() { restart(1 << 3); }
void rst_2() { restart(2); } void rst_2() { restart(2 << 3); }
void rst_3() { restart(3); } void rst_3() { restart(3 << 3); }
void rst_4() { restart(4); } void rst_4() { restart(4 << 3); }
void rst_5() { restart(5); } void rst_5() { restart(5 << 3); }
void rst_6() { restart(6); } void rst_6() { restart(6 << 3); }
void rst_7() { restart(7); } void rst_7() { restart(7 << 3); }
// increment and decrement // increment and decrement
@@ -689,8 +646,8 @@ namespace EightBit {
// control // control
void ei() { enableInterrupts(); } void ei() { m_interrupt = true; }
void di() { disableInterrupts(); } void di() { m_interrupt = false; }
void nop() {} void nop() {}
+1 -1
View File
@@ -52,7 +52,7 @@ void EightBit::Intel8080::installInstructions() {
/* A */ INS(BIND(ana_b), Implied, "ANA B", 4), INS(BIND(ana_c), Implied, "ANA C", 4), INS(BIND(ana_d), Implied, "ANA D", 4), INS(BIND(ana_e), Implied, "ANA E", 4), INS(BIND(ana_h), Implied, "ANA H", 4), INS(BIND(ana_l), Implied, "ANA L", 4), INS(BIND(ana_m), Implied, "ANA M", 7), INS(BIND(ana_a), Implied, "ANA A", 4), INS(BIND(xra_b), Implied, "XRA B", 4), INS(BIND(xra_c), Implied, "XRA C", 4), INS(BIND(xra_d), Implied, "XRA D", 4), INS(BIND(xra_e), Implied, "XRA E", 4), INS(BIND(xra_h), Implied, "XRA H", 4), INS(BIND(xra_l), Implied, "XRA L", 4), INS(BIND(xra_m), Implied, "XRA M", 4), INS(BIND(xra_a), Implied, "XRA A", 4), // A /* A */ INS(BIND(ana_b), Implied, "ANA B", 4), INS(BIND(ana_c), Implied, "ANA C", 4), INS(BIND(ana_d), Implied, "ANA D", 4), INS(BIND(ana_e), Implied, "ANA E", 4), INS(BIND(ana_h), Implied, "ANA H", 4), INS(BIND(ana_l), Implied, "ANA L", 4), INS(BIND(ana_m), Implied, "ANA M", 7), INS(BIND(ana_a), Implied, "ANA A", 4), INS(BIND(xra_b), Implied, "XRA B", 4), INS(BIND(xra_c), Implied, "XRA C", 4), INS(BIND(xra_d), Implied, "XRA D", 4), INS(BIND(xra_e), Implied, "XRA E", 4), INS(BIND(xra_h), Implied, "XRA H", 4), INS(BIND(xra_l), Implied, "XRA L", 4), INS(BIND(xra_m), Implied, "XRA M", 4), INS(BIND(xra_a), Implied, "XRA A", 4), // A
/* B */ INS(BIND(ora_b), Implied, "ORA B", 4), INS(BIND(ora_c), Implied, "ORA C", 4), INS(BIND(ora_d), Implied, "ORA D", 4), INS(BIND(ora_e), Implied, "ORA E", 4), INS(BIND(ora_h), Implied, "ORA H", 4), INS(BIND(ora_l), Implied, "ORA L", 4), INS(BIND(ora_m), Implied, "ORA M", 7), INS(BIND(ora_a), Implied, "ORA A", 4), INS(BIND(cmp_b), Implied, "CMP B", 4), INS(BIND(cmp_c), Implied, "CMP C", 4), INS(BIND(cmp_d), Implied, "CMP D", 4), INS(BIND(cmp_e), Implied, "CMP E", 4), INS(BIND(cmp_h), Implied, "CMP H", 4), INS(BIND(cmp_l), Implied, "CMP L", 4), INS(BIND(cmp_m), Implied, "CMP M", 4), INS(BIND(cmp_a), Implied, "CMP A", 4), // B /* B */ INS(BIND(ora_b), Implied, "ORA B", 4), INS(BIND(ora_c), Implied, "ORA C", 4), INS(BIND(ora_d), Implied, "ORA D", 4), INS(BIND(ora_e), Implied, "ORA E", 4), INS(BIND(ora_h), Implied, "ORA H", 4), INS(BIND(ora_l), Implied, "ORA L", 4), INS(BIND(ora_m), Implied, "ORA M", 7), INS(BIND(ora_a), Implied, "ORA A", 4), INS(BIND(cmp_b), Implied, "CMP B", 4), INS(BIND(cmp_c), Implied, "CMP C", 4), INS(BIND(cmp_d), Implied, "CMP D", 4), INS(BIND(cmp_e), Implied, "CMP E", 4), INS(BIND(cmp_h), Implied, "CMP H", 4), INS(BIND(cmp_l), Implied, "CMP L", 4), INS(BIND(cmp_m), Implied, "CMP M", 4), INS(BIND(cmp_a), Implied, "CMP A", 4), // B
/* C */ INS(BIND(rnz), Implied, "RNZ", 5), INS(BIND(pop_b), Implied, "POP B", 10), INS(BIND(jnz), Absolute, "JNZ ", 10), INS(BIND(jmp), Absolute, "JMP ", 10), INS(BIND(cnz), Absolute, "CNZ ", 11), INS(BIND(push_b), Implied, "PUSH B", 11), INS(BIND(adi), Immediate, "ADI ", 7), INS(BIND(rst_0), Implied, "RST 0", 11), INS(BIND(rz), Implied, "RZ", 11), INS(BIND(ret), Implied, "RET", 10), INS(BIND(jz), Absolute, "JZ ", 10), UNKNOWN(), INS(BIND(cz), Absolute, "CZ ", 11), INS(BIND(call), Absolute, "CALL ", 17), INS(BIND(aci), Immediate, "ACI ", 7), INS(BIND(rst_1), Implied, "RST 1", 11), // C /* C */ INS(BIND(rnz), Implied, "RNZ", 5), INS(BIND(pop_b), Implied, "POP B", 10), INS(BIND(jnz), Absolute, "JNZ ", 10), INS(BIND(jmp), Absolute, "JMP ", 10), INS(BIND(cnz), Absolute, "CNZ ", 11), INS(BIND(push_b), Implied, "PUSH B", 11), INS(BIND(adi), Immediate, "ADI ", 7), INS(BIND(rst_0), Implied, "RST 0", 11), INS(BIND(rz), Implied, "RZ", 11), INS(BIND(ret), Implied, "RET", 10), INS(BIND(jz), Absolute, "JZ ", 10), UNKNOWN(), INS(BIND(cz), Absolute, "CZ ", 11), INS(BIND(callDirect), Absolute, "CALL ", 17), INS(BIND(aci), Immediate, "ACI ", 7), INS(BIND(rst_1), Implied, "RST 1", 11), // C
/* D */ INS(BIND(rnc), Implied, "RNC", 5), INS(BIND(pop_d), Implied, "POP D", 10), INS(BIND(jnc), Absolute, "JNC ", 10), INS(BIND(out), Immediate, "OUT ", 10), INS(BIND(cnc), Absolute, "CNC ", 11), INS(BIND(push_d), Implied, "PUSH D", 11), INS(BIND(sui), Immediate, "SUI ", 7), INS(BIND(rst_2), Implied, "RST 2", 11), INS(BIND(rc), Implied, "RC", 11), UNKNOWN(), INS(BIND(jc), Absolute, "JC ", 10), INS(BIND(in), Immediate, "IN ", 10), INS(BIND(cc), Absolute, "CC ", 11), UNKNOWN(), INS(BIND(sbi), Immediate, "SBI ", 7), INS(BIND(rst_3), Implied, "RST 3", 11), // D /* D */ INS(BIND(rnc), Implied, "RNC", 5), INS(BIND(pop_d), Implied, "POP D", 10), INS(BIND(jnc), Absolute, "JNC ", 10), INS(BIND(out), Immediate, "OUT ", 10), INS(BIND(cnc), Absolute, "CNC ", 11), INS(BIND(push_d), Implied, "PUSH D", 11), INS(BIND(sui), Immediate, "SUI ", 7), INS(BIND(rst_2), Implied, "RST 2", 11), INS(BIND(rc), Implied, "RC", 11), UNKNOWN(), INS(BIND(jc), Absolute, "JC ", 10), INS(BIND(in), Immediate, "IN ", 10), INS(BIND(cc), Absolute, "CC ", 11), UNKNOWN(), INS(BIND(sbi), Immediate, "SBI ", 7), INS(BIND(rst_3), Implied, "RST 3", 11), // D
/* E */ INS(BIND(rpo), Implied, "RPO", 5), INS(BIND(pop_h), Implied, "POP H", 10), INS(BIND(jpo), Absolute, "JPO ", 10), INS(BIND(xhtl), Implied, "XHTL", 18), INS(BIND(cpo), Absolute, "CPO ", 11), INS(BIND(push_h), Implied, "PUSH H", 11), INS(BIND(ani), Immediate, "ANI ", 7), INS(BIND(rst_4), Implied, "RST 4", 11), INS(BIND(rpe), Implied, "RPE", 11), INS(BIND(pchl), Implied, "PCHL", 5), INS(BIND(jpe), Absolute, "JPE ", 10), INS(BIND(xchg), Implied, "XCHG", 4), INS(BIND(cpe), Absolute, "CPE ", 11), UNKNOWN(), INS(BIND(xri), Immediate, "XRI ", 7), INS(BIND(rst_5), Implied, "RST 5", 11), // E /* E */ INS(BIND(rpo), Implied, "RPO", 5), INS(BIND(pop_h), Implied, "POP H", 10), INS(BIND(jpo), Absolute, "JPO ", 10), INS(BIND(xhtl), Implied, "XHTL", 18), INS(BIND(cpo), Absolute, "CPO ", 11), INS(BIND(push_h), Implied, "PUSH H", 11), INS(BIND(ani), Immediate, "ANI ", 7), INS(BIND(rst_4), Implied, "RST 4", 11), INS(BIND(rpe), Implied, "RPE", 11), INS(BIND(pchl), Implied, "PCHL", 5), INS(BIND(jpe), Absolute, "JPE ", 10), INS(BIND(xchg), Implied, "XCHG", 4), INS(BIND(cpe), Absolute, "CPE ", 11), UNKNOWN(), INS(BIND(xri), Immediate, "XRI ", 7), INS(BIND(rst_5), Implied, "RST 5", 11), // E
/* F */ INS(BIND(rp), Implied, "RP", 5), INS(BIND(pop_psw), Implied, "POP PSW", 10), INS(BIND(jp), Absolute, "JP ", 10), INS(BIND(di), Implied, "DI ", 4), INS(BIND(cp), Absolute, "CP ", 11), INS(BIND(push_psw), Implied, "PUSH PSW", 11), INS(BIND(ori), Immediate, "ORI ", 7), INS(BIND(rst_6), Implied, "RST 6", 11), INS(BIND(rm), Implied, "RM", 11), INS(BIND(sphl), Implied, "SPHL", 5), INS(BIND(jm), Absolute, "JM ", 10), INS(BIND(ei), Implied, "EI", 4), INS(BIND(cm), Absolute, "CM ", 11), UNKNOWN(), INS(BIND(cpi), Immediate, "CPI ", 7), INS(BIND(rst_7), Implied, "RST 7", 11), // F /* F */ INS(BIND(rp), Implied, "RP", 5), INS(BIND(pop_psw), Implied, "POP PSW", 10), INS(BIND(jp), Absolute, "JP ", 10), INS(BIND(di), Implied, "DI ", 4), INS(BIND(cp), Absolute, "CP ", 11), INS(BIND(push_psw), Implied, "PUSH PSW", 11), INS(BIND(ori), Immediate, "ORI ", 7), INS(BIND(rst_6), Implied, "RST 6", 11), INS(BIND(rm), Implied, "RM", 11), INS(BIND(sphl), Implied, "SPHL", 5), INS(BIND(jm), Absolute, "JM ", 10), INS(BIND(ei), Implied, "EI", 4), INS(BIND(cm), Absolute, "CM ", 11), UNKNOWN(), INS(BIND(cpi), Immediate, "CPI ", 7), INS(BIND(rst_7), Implied, "RST 7", 11), // F
+4 -14
View File
@@ -155,22 +155,12 @@ namespace EightBit {
void postIncrement(uint8_t value); void postIncrement(uint8_t value);
void postDecrement(uint8_t value); void postDecrement(uint8_t value);
void restart(uint8_t address);
void jrConditional(int conditional);
void jrConditionalFlag(int flag);
void ret();
void reti(); void reti();
void returnConditional(int condition); bool jrConditionalFlag(int flag);
void returnConditionalFlag(int flag); bool returnConditionalFlag(int flag);
bool jumpConditionalFlag(int flag);
void jumpConditional(int condition); bool callConditionalFlag(int flag);
void jumpConditionalFlag(int flag);
void callConditional(int condition);
void callConditionalFlag(int flag);
void sbc(register16_t& operand, register16_t value); void sbc(register16_t& operand, register16_t value);
void adc(register16_t& operand, register16_t value); void adc(register16_t& operand, register16_t value);
+100 -146
View File
@@ -8,26 +8,23 @@ EightBit::LR35902::LR35902(Bus& memory)
: IntelProcessor(memory), : IntelProcessor(memory),
m_ime(false), m_ime(false),
m_prefixCB(false) { m_prefixCB(false) {
MEMPTR().word = 0;
} }
void EightBit::LR35902::reset() { void EightBit::LR35902::reset() {
Processor::reset(); IntelProcessor::reset();
sp.word = 0xfffe; sp.word = 0xfffe;
di(); di();
} }
void EightBit::LR35902::initialise() { void EightBit::LR35902::initialise() {
Processor::initialise(); IntelProcessor::initialise();
AF().word = 0xffff; AF().word = 0xffff;
BC().word = 0xffff; BC().word = 0xffff;
DE().word = 0xffff; DE().word = 0xffff;
HL().word = 0xffff; HL().word = 0xffff;
MEMPTR().word = 0;
m_prefixCB = false; m_prefixCB = false;
} }
@@ -72,89 +69,32 @@ void EightBit::LR35902::postDecrement(uint8_t value) {
#pragma region PC manipulation: call/ret/jp/jr #pragma region PC manipulation: call/ret/jp/jr
void EightBit::LR35902::restart(uint8_t address) { bool EightBit::LR35902::jrConditionalFlag(int flag) {
pushWord(pc);
pc.low = address;
pc.high = 0;
}
void EightBit::LR35902::jrConditional(int conditional) {
auto offset = (int8_t)fetchByte();
if (conditional) {
pc.word += offset;
cycles++;
}
}
void EightBit::LR35902::jrConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
jrConditional(!(F() & ZF)); return jrConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
jrConditional(F() & ZF); return jrConditional(F() & ZF);
break;
case 2: // NC case 2: // NC
jrConditional(!(F() & CF)); return jrConditional(!(F() & CF));
break;
case 3: // C case 3: // C
jrConditional(F() & CF); return jrConditional(F() & CF);
break;
case 4: // PO
case 5: // PE
case 6: // P
case 7: // M
cycles -= 2;
break;
} }
throw std::logic_error("Unhandled JR conditional");
} }
void EightBit::LR35902::jumpConditional(int conditional) { bool EightBit::LR35902::jumpConditionalFlag(int flag) {
if (conditional)
pc = MEMPTR();
}
void EightBit::LR35902::jumpConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
jumpConditional(!(F() & ZF)); return jumpConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
jumpConditional(F() & ZF); return jumpConditional(F() & ZF);
break;
case 2: // NC case 2: // NC
jumpConditional(!(F() & CF)); return jumpConditional(!(F() & CF));
break;
case 3: // C case 3: // C
jumpConditional(F() & CF); return jumpConditional(F() & CF);
break;
case 4: // GB: LD (FF00 + C),A
m_memory.set(0xff00 + C(), A());
cycles--; // Giving 8 cycles
break;
case 5: // GB: LD (nn),A
fetchWord();
m_memory.ADDRESS() = MEMPTR();
m_memory.reference() = A();
cycles++; // Giving 16 cycles
break;
case 6: // GB: LD A,(FF00 + C)
m_memory.ADDRESS().word = 0xff00 + C();
A() = m_memory.reference();
cycles--; // 8 cycles
break;
case 7: // GB: LD A,(nn)
fetchWord();
m_memory.ADDRESS() = MEMPTR();
A() = m_memory.reference();
cycles++; // Giving 16 cycles
break;
} }
} throw std::logic_error("Unhandled JP conditional");
void EightBit::LR35902::ret() {
popWord(MEMPTR());
pc = MEMPTR();
} }
void EightBit::LR35902::reti() { void EightBit::LR35902::reti() {
@@ -162,86 +102,35 @@ void EightBit::LR35902::reti() {
ei(); ei();
} }
void EightBit::LR35902::returnConditional(int condition) { bool EightBit::LR35902::returnConditionalFlag(int flag) {
if (condition) {
ret();
cycles += 3;
}
}
void EightBit::LR35902::returnConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
returnConditional(!(F() & ZF)); return returnConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
returnConditional(F() & ZF); return returnConditional(F() & ZF);
break; break;
case 2: // NC case 2: // NC
returnConditional(!(F() & CF)); return returnConditional(!(F() & CF));
break; break;
case 3: // C case 3: // C
returnConditional(F() & CF); return returnConditional(F() & CF);
break;
case 4: // GB: LD (FF00 + n),A
m_memory.set(0xff00 + fetchByte(), A());
cycles++; // giving 12 cycles in total
break;
case 5: { // GB: ADD SP,dd
auto before = sp;
auto value = fetchByte();
sp.word += (int8_t)value;
clearFlag(ZF | NF);
setFlag(CF, sp.word & Bit16);
adjustHalfCarryAdd(before.high, value, sp.high);
}
cycles += 2; // 16 cycles
break;
case 6: // GB: LD A,(FF00 + n)
A() = m_memory.get(0xff00 + fetchByte());
cycles++; // 12 cycles
break;
case 7: { // GB: LD HL,SP + dd
auto before = sp;
auto value = fetchByte();
HL().word = before.word + (int8_t)value;
clearFlag(ZF | NF);
setFlag(CF, HL().word & Bit16);
adjustHalfCarryAdd(before.high, value, HL().high);
}
cycles++; // 12 cycles
break; break;
} }
throw std::logic_error("Unhandled RET conditional");
} }
void EightBit::LR35902::callConditional(int condition) { bool EightBit::LR35902::callConditionalFlag(int flag) {
if (condition) {
call();
cycles += 3;
}
}
void EightBit::LR35902::callConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
callConditional(!(F() & ZF)); return callConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
callConditional(F() & ZF); return callConditional(F() & ZF);
break;
case 2: // NC case 2: // NC
callConditional(!(F() & CF)); return callConditional(!(F() & CF));
break;
case 3: // C case 3: // C
callConditional(F() & CF); return callConditional(F() & CF);
break;
case 4:
case 5:
case 6:
case 7:
cycles -= 3; // removed from GB
break;
} }
throw std::logic_error("Unhandled CALL conditional");
} }
#pragma endregion PC manipulation: call/ret/jp/jr #pragma endregion PC manipulation: call/ret/jp/jr
@@ -618,12 +507,17 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
cycles++; cycles++;
break; break;
case 3: // JR d case 3: // JR d
jrConditional(true); jr(fetchByte());
cycles += 3; cycles += 4;
break; break;
default: // JR cc,d default: { // JR cc,d
jrConditionalFlag(y - 4); auto condition = y - 4;
cycles += 2; if (y < 4) {
if (jrConditionalFlag(condition))
cycles++;
cycles += 2;
}
}
break; break;
} }
break; break;
@@ -786,8 +680,42 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
case 3: case 3:
switch (z) { switch (z) {
case 0: // Conditional return case 0: // Conditional return
returnConditionalFlag(y); if (y < 4) {
cycles += 2; if (returnConditionalFlag(y))
cycles += 3;
cycles += 2;
} else {
switch (y) {
case 4: // GB: LD (FF00 + n),A
m_memory.set(0xff00 + fetchByte(), A());
cycles += 3;
break;
case 5: { // GB: ADD SP,dd
auto before = sp;
auto value = fetchByte();
sp.word += (int8_t)value;
clearFlag(ZF | NF);
setFlag(CF, sp.word & Bit16);
adjustHalfCarryAdd(before.high, value, sp.high);
}
cycles += 4;
break;
case 6: // GB: LD A,(FF00 + n)
A() = m_memory.get(0xff00 + fetchByte());
cycles += 3;
break;
case 7: { // GB: LD HL,SP + dd
auto before = sp;
auto value = fetchByte();
HL().word = before.word + (int8_t)value;
clearFlag(ZF | NF);
setFlag(CF, HL().word & Bit16);
adjustHalfCarryAdd(before.high, value, HL().high);
}
cycles += 3;
break;
}
}
break; break;
case 1: // POP & various ops case 1: // POP & various ops
switch (q) { switch (q) {
@@ -817,8 +745,34 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
} }
break; break;
case 2: // Conditional jump case 2: // Conditional jump
jumpConditionalFlag(y); if (y < 4) {
cycles += 3; jumpConditionalFlag(y);
cycles += 3;
} else {
switch (y) {
case 4: // GB: LD (FF00 + C),A
m_memory.set(0xff00 + C(), A());
cycles += 2;
break;
case 5: // GB: LD (nn),A
fetchWord();
m_memory.ADDRESS() = MEMPTR();
m_memory.reference() = A();
cycles += 4;
break;
case 6: // GB: LD A,(FF00 + C)
m_memory.ADDRESS().word = 0xff00 + C();
A() = m_memory.reference();
cycles += 2;
break;
case 7: // GB: LD A,(nn)
fetchWord();
m_memory.ADDRESS() = MEMPTR();
A() = m_memory.reference();
cycles += 4;
break;
}
}
break; break;
case 3: // Assorted operations case 3: // Assorted operations
switch (y) { switch (y) {
+8 -31
View File
@@ -24,8 +24,8 @@ namespace EightBit {
Signal<Z80> ExecutingInstruction; Signal<Z80> ExecutingInstruction;
void disableInterrupts(); void di();
void enableInterrupts(); void ei();
int interruptMaskable(uint8_t value) { return interrupt(true, value); } int interruptMaskable(uint8_t value) { return interrupt(true, value); }
int interruptMaskable() { return interruptMaskable(0); } int interruptMaskable() { return interruptMaskable(0); }
@@ -126,19 +126,7 @@ namespace EightBit {
int fetchExecute() { int fetchExecute() {
M1() = true; M1() = true;
return execute(fetchByteExecute()); return execute(fetchByte());
}
uint8_t fetchByteExecute() {
if (!getM1())
throw std::logic_error("M1 cannot be high");
return fetchByte();
}
uint8_t fetchByteData() {
if (getM1())
throw std::logic_error("M1 cannot be low");
return fetchByte();
} }
void incrementRefresh() { void incrementRefresh() {
@@ -180,7 +168,7 @@ namespace EightBit {
return ALT_HL().low; return ALT_HL().low;
case 6: case 6:
if (m_prefixDD || m_prefixFD) { if (m_prefixDD || m_prefixFD) {
m_displacement = fetchByteData(); m_displacement = fetchByte();
return DISPLACED(); return DISPLACED();
} }
m_memory.ADDRESS() = HL(); m_memory.ADDRESS() = HL();
@@ -330,24 +318,13 @@ namespace EightBit {
void postIncrement(uint8_t value); void postIncrement(uint8_t value);
void postDecrement(uint8_t value); void postDecrement(uint8_t value);
void restart(uint8_t address);
void jrConditional(int conditional);
void jrConditionalFlag(int flag);
void ret();
void retn(); void retn();
void reti(); void reti();
void returnConditional(int condition); bool jrConditionalFlag(int flag);
void returnConditionalFlag(int flag); bool returnConditionalFlag(int flag);
bool jumpConditionalFlag(int flag);
void jumpConditional(int condition); bool callConditionalFlag(int flag);
void jumpConditionalFlag(int flag);
virtual void call() override;
void callConditional(int condition);
void callConditionalFlag(int flag);
void sbc(register16_t& operand, register16_t value); void sbc(register16_t& operand, register16_t value);
void adc(register16_t& operand, register16_t value); void adc(register16_t& operand, register16_t value);
+70 -138
View File
@@ -25,7 +25,7 @@ EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
void EightBit::Z80::reset() { void EightBit::Z80::reset() {
IntelProcessor::reset(); IntelProcessor::reset();
IFF1() = IFF2() = false; di();
} }
void EightBit::Z80::initialise() { void EightBit::Z80::initialise() {
@@ -63,11 +63,11 @@ void EightBit::Z80::initialise() {
#pragma region Interrupt routines #pragma region Interrupt routines
void EightBit::Z80::disableInterrupts() { void EightBit::Z80::di() {
IFF1() = IFF2() = false; IFF1() = IFF2() = false;
} }
void EightBit::Z80::enableInterrupts() { void EightBit::Z80::ei() {
IFF1() = IFF2() = true; IFF1() = IFF2() = true;
} }
@@ -75,7 +75,7 @@ int EightBit::Z80::interrupt(bool maskable, uint8_t value) {
cycles = 0; cycles = 0;
if (!maskable || (maskable && IFF1())) { if (!maskable || (maskable && IFF1())) {
if (maskable) { if (maskable) {
disableInterrupts(); di();
switch (IM()) { switch (IM()) {
case 0: case 0:
M1() = true; M1() = true;
@@ -93,7 +93,7 @@ int EightBit::Z80::interrupt(bool maskable, uint8_t value) {
break; break;
} }
} else { } else {
IFF1() = 0; IFF1() = false;
restart(0x66); restart(0x66);
cycles += 13; cycles += 13;
} }
@@ -163,87 +163,48 @@ void EightBit::Z80::postDecrement(uint8_t value) {
#pragma region PC manipulation: call/ret/jp/jr #pragma region PC manipulation: call/ret/jp/jr
void EightBit::Z80::restart(uint8_t address) { bool EightBit::Z80::jrConditionalFlag(int flag) {
pushWord(pc);
pc.low = MEMPTR().low = address;
pc.high = MEMPTR().high = 0;
}
void EightBit::Z80::jrConditional(int conditional) {
auto offset = (int8_t)fetchByteData();
if (conditional) {
MEMPTR().word = pc.word + offset;
pc = MEMPTR();
cycles += 5;
}
}
void EightBit::Z80::jrConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
jrConditional(!(F() & ZF)); return jrConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
jrConditional(F() & ZF); return jrConditional(F() & ZF);
break;
case 2: // NC case 2: // NC
jrConditional(!(F() & CF)); return jrConditional(!(F() & CF));
break;
case 3: // C case 3: // C
jrConditional(F() & CF); return jrConditional(F() & CF);
break;
case 4: // PO case 4: // PO
jrConditional(!(F() & PF)); return jrConditional(!(F() & PF));
break;
case 5: // PE case 5: // PE
jrConditional(F() & PF); return jrConditional(F() & PF);
break;
case 6: // P case 6: // P
jrConditional(!(F() & SF)); return jrConditional(!(F() & SF));
break;
case 7: // M case 7: // M
jrConditional(F() & SF); return jrConditional(F() & SF);
break;
} }
throw std::logic_error("Unhandled JR conditional");
} }
void EightBit::Z80::jumpConditional(int conditional) { bool EightBit::Z80::jumpConditionalFlag(int flag) {
if (conditional)
pc = MEMPTR();
}
void EightBit::Z80::jumpConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
jumpConditional(!(F() & ZF)); return jumpConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
jumpConditional(F() & ZF); return jumpConditional(F() & ZF);
break;
case 2: // NC case 2: // NC
jumpConditional(!(F() & CF)); return jumpConditional(!(F() & CF));
break;
case 3: // C case 3: // C
jumpConditional(F() & CF); return jumpConditional(F() & CF);
break;
case 4: // PO case 4: // PO
jumpConditional(!(F() & PF)); return jumpConditional(!(F() & PF));
break;
case 5: // PE case 5: // PE
jumpConditional(F() & PF); return jumpConditional(F() & PF);
break;
case 6: // P case 6: // P
jumpConditional(!(F() & SF)); return jumpConditional(!(F() & SF));
break;
case 7: // M case 7: // M
jumpConditional(F() & SF); return jumpConditional(F() & SF);
break;
} }
} throw std::logic_error("Unhandled JP conditional");
void EightBit::Z80::ret() {
popWord(MEMPTR());
pc = MEMPTR();
} }
void EightBit::Z80::retn() { void EightBit::Z80::retn() {
@@ -255,79 +216,48 @@ void EightBit::Z80::reti() {
retn(); retn();
} }
void EightBit::Z80::returnConditional(int condition) { bool EightBit::Z80::returnConditionalFlag(int flag) {
if (condition) {
ret();
cycles += 6;
}
}
void EightBit::Z80::returnConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
returnConditional(!(F() & ZF)); return returnConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
returnConditional(F() & ZF); return returnConditional(F() & ZF);
break;
case 2: // NC case 2: // NC
returnConditional(!(F() & CF)); return returnConditional(!(F() & CF));
break;
case 3: // C case 3: // C
returnConditional(F() & CF); return returnConditional(F() & CF);
break;
case 4: // PO case 4: // PO
returnConditional(!(F() & PF)); return returnConditional(!(F() & PF));
break;
case 5: // PE case 5: // PE
returnConditional(F() & PF); return returnConditional(F() & PF);
break;
case 6: // P case 6: // P
returnConditional(!(F() & SF)); return returnConditional(!(F() & SF));
break;
case 7: // M case 7: // M
returnConditional(F() & SF); return returnConditional(F() & SF);
break;
} }
throw std::logic_error("Unhandled RET conditional");
} }
void EightBit::Z80::call() { bool EightBit::Z80::callConditionalFlag(int flag) {
IntelProcessor::call();
cycles += 7;
}
void EightBit::Z80::callConditional(int condition) {
if (condition)
call();
}
void EightBit::Z80::callConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
callConditional(!(F() & ZF)); return callConditional(!(F() & ZF));
break;
case 1: // Z case 1: // Z
callConditional(F() & ZF); return callConditional(F() & ZF);
break;
case 2: // NC case 2: // NC
callConditional(!(F() & CF)); return callConditional(!(F() & CF));
break;
case 3: // C case 3: // C
callConditional(F() & CF); return callConditional(F() & CF);
break;
case 4: // PO case 4: // PO
callConditional(!(F() & PF)); return callConditional(!(F() & PF));
break;
case 5: // PE case 5: // PE
callConditional(F() & PF); return callConditional(F() & PF);
break;
case 6: // P case 6: // P
callConditional(!(F() & SF)); return callConditional(!(F() & SF));
break;
case 7: // M case 7: // M
callConditional(F() & SF); return callConditional(F() & SF);
break;
} }
throw std::logic_error("Unhandled CALL conditional");
} }
#pragma endregion PC manipulation: call/ret/jp/jr #pragma endregion PC manipulation: call/ret/jp/jr
@@ -1248,15 +1178,17 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 4; cycles += 4;
break; break;
case 2: // DJNZ d case 2: // DJNZ d
jrConditional(--B()); if (jrConditional(--B()))
cycles += 5;
cycles += 8; cycles += 8;
break; break;
case 3: // JR d case 3: // JR d
jrConditional(true); jr(fetchByte());
cycles += 7; cycles += 12;
break; break;
default: // JR cc,d default: // JR cc,d
jrConditionalFlag(y - 4); if (jrConditionalFlag(y - 4))
cycles += 5;
cycles += 5; cycles += 5;
break; break;
} }
@@ -1347,7 +1279,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 7; cycles += 7;
break; break;
case 6: { // 8-bit load immediate case 6: { // 8-bit load immediate
R(y) = fetchByteData(); // LD r,n R(y) = fetchByte(); // LD r,n
cycles += 7; cycles += 7;
if (y == 6) if (y == 6)
cycles += 3; cycles += 3;
@@ -1455,7 +1387,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 3: case 3:
switch (z) { switch (z) {
case 0: // Conditional return case 0: // Conditional return
returnConditionalFlag(y); if (returnConditionalFlag(y))
cycles += 6;
cycles += 5; cycles += 5;
break; break;
case 1: // POP & various ops case 1: // POP & various ops
@@ -1486,7 +1419,6 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
} }
break; break;
case 2: // Conditional jump case 2: // Conditional jump
fetchWord();
jumpConditionalFlag(y); jumpConditionalFlag(y);
cycles += 10; cycles += 10;
break; break;
@@ -1494,17 +1426,17 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
switch (y) { switch (y) {
case 0: // JP nn case 0: // JP nn
fetchWord(); fetchWord();
pc = MEMPTR(); jump();
cycles += 10; cycles += 10;
break; break;
case 1: // CB prefix case 1: // CB prefix
m_prefixCB = true; m_prefixCB = true;
if (m_prefixDD || m_prefixFD) if (m_prefixDD || m_prefixFD)
m_displacement = fetchByteData(); m_displacement = fetchByte();
fetchExecute(); fetchExecute();
break; break;
case 2: // OUT (n),A case 2: // OUT (n),A
m_memory.ADDRESS().low = fetchByteData(); m_memory.ADDRESS().low = fetchByte();
m_memory.ADDRESS().high = A(); m_memory.ADDRESS().high = A();
MEMPTR() = m_memory.ADDRESS(); MEMPTR() = m_memory.ADDRESS();
m_memory.placeDATA(A()); m_memory.placeDATA(A());
@@ -1513,7 +1445,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 11; cycles += 11;
break; break;
case 3: // IN A,(n) case 3: // IN A,(n)
m_memory.ADDRESS().low = fetchByteData(); m_memory.ADDRESS().low = fetchByte();
m_memory.ADDRESS().high = A(); m_memory.ADDRESS().high = A();
MEMPTR() = m_memory.ADDRESS(); MEMPTR() = m_memory.ADDRESS();
readPort(); readPort();
@@ -1530,18 +1462,18 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 4; cycles += 4;
break; break;
case 6: // DI case 6: // DI
disableInterrupts(); di();
cycles += 4; cycles += 4;
break; break;
case 7: // EI case 7: // EI
enableInterrupts(); ei();
cycles += 4; cycles += 4;
break; break;
} }
break; break;
case 4: // Conditional call: CALL cc[y], nn case 4: // Conditional call: CALL cc[y], nn
fetchWord(); if (callConditionalFlag(y))
callConditionalFlag(y); cycles += 7;
cycles += 10; cycles += 10;
break; break;
case 5: // PUSH & various ops case 5: // PUSH & various ops
@@ -1575,28 +1507,28 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 6: // Operate on accumulator and immediate operand: alu[y] n case 6: // Operate on accumulator and immediate operand: alu[y] n
switch (y) { switch (y) {
case 0: // ADD A,n case 0: // ADD A,n
add(A(), fetchByteData()); add(A(), fetchByte());
break; break;
case 1: // ADC A,n case 1: // ADC A,n
adc(A(), fetchByteData()); adc(A(), fetchByte());
break; break;
case 2: // SUB n case 2: // SUB n
sub(A(), fetchByteData()); sub(A(), fetchByte());
break; break;
case 3: // SBC A,n case 3: // SBC A,n
sbc(A(), fetchByteData()); sbc(A(), fetchByte());
break; break;
case 4: // AND n case 4: // AND n
andr(A(), fetchByteData()); andr(A(), fetchByte());
break; break;
case 5: // XOR n case 5: // XOR n
xorr(A(), fetchByteData()); xorr(A(), fetchByte());
break; break;
case 6: // OR n case 6: // OR n
orr(A(), fetchByteData()); orr(A(), fetchByte());
break; break;
case 7: // CP n case 7: // CP n
compare(fetchByteData()); compare(fetchByte());
break; break;
} }
cycles += 7; cycles += 7;
+51 -4
View File
@@ -6,8 +6,6 @@ namespace EightBit {
class IntelProcessor : public Processor class IntelProcessor : public Processor
{ {
public: public:
virtual ~IntelProcessor();
register16_t& MEMPTR() { return m_memptr; } register16_t& MEMPTR() { return m_memptr; }
virtual void initialise(); virtual void initialise();
@@ -42,11 +40,60 @@ namespace EightBit {
Processor::fetchWord(MEMPTR()); Processor::fetchWord(MEMPTR());
} }
virtual void call() { //
pushWord(pc);
void jump() {
pc = MEMPTR(); pc = MEMPTR();
} }
void call() {
pushWord(pc);
jump();
}
void restart(uint8_t address) {
MEMPTR().low = address;
MEMPTR().high = 0;
call();
}
bool callConditional(int condition) {
fetchWord();
if (condition)
call();
return condition != 0;
}
bool jumpConditional(int conditional) {
fetchWord();
if (conditional)
jump();
return conditional != 0;
}
void ret() {
popWord(MEMPTR());
jump();
}
bool returnConditional(int condition) {
if (condition)
ret();
return condition != 0;
}
void jr(int8_t offset) {
MEMPTR().word = pc.word + offset;
jump();
}
bool jrConditional(int conditional) {
auto offset = fetchByte();
if (conditional)
jr(offset);
return conditional != 0;
}
private: private:
register16_t m_memptr; register16_t m_memptr;
}; };
-4
View File
@@ -6,15 +6,11 @@ EightBit::IntelProcessor::IntelProcessor(Memory& memory)
MEMPTR().word = 0; MEMPTR().word = 0;
} }
EightBit::IntelProcessor::~IntelProcessor() {
}
void EightBit::IntelProcessor::initialise() { void EightBit::IntelProcessor::initialise() {
Processor::initialise(); Processor::initialise();
MEMPTR().word = 0; MEMPTR().word = 0;
} }
void EightBit::IntelProcessor::push(uint8_t value) { void EightBit::IntelProcessor::push(uint8_t value) {
m_memory.ADDRESS().word = --sp.word; m_memory.ADDRESS().word = --sp.word;
m_memory.reference() = value; m_memory.reference() = value;