mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2026-04-26 21:18:36 +00:00
Further work on uniting the 8080 family processor family.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
1 parent
627e41bf35
commit
0291970427
8 files changed
+273
-420
No files matched your search
+39
-82
@@ -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() {}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in new issue
Block a user