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 2017-06-11 21:08:40 +01:00
parent 627e41bf35
commit 0291970427
8 changed files with 273 additions and 420 deletions

View File

@ -50,12 +50,9 @@ namespace EightBit {
return m_interrupt;
}
void disableInterrupts() { m_interrupt = false; }
void enableInterrupts() { m_interrupt = true; }
int interrupt(uint8_t value) {
if (isInterruptable()) {
disableInterrupts();
di();
return execute(value);
}
return 0;
@ -133,42 +130,6 @@ namespace EightBit {
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) {
F().AC = (((A() | value) & 0x8) != 0);
F().C = false;
@ -391,19 +352,19 @@ namespace EightBit {
// jump
void jmp() { jmpConditional(true); }
void jmp() { jumpConditional(true); }
void jc() { jmpConditional(F().C); }
void jnc() { jmpConditional(!F().C); }
void jc() { jumpConditional(F().C); }
void jnc() { jumpConditional(!F().C); }
void jz() { jmpConditional(F().Z); }
void jnz() { jmpConditional(!F().Z); }
void jz() { jumpConditional(F().Z); }
void jnz() { jumpConditional(!F().Z); }
void jpe() { jmpConditional(F().P); }
void jpo() { jmpConditional(!F().P); }
void jpe() { jumpConditional(F().P); }
void jpo() { jumpConditional(!F().P); }
void jm() { jmpConditional(F().S); }
void jp() { jmpConditional(!F().S); }
void jm() { jumpConditional(F().S); }
void jp() { jumpConditional(!F().S); }
void pchl() {
pc = HL();
@ -411,51 +372,47 @@ namespace EightBit {
// call
virtual void call() override {
auto destination = m_memory.getWord(pc.word);
callAddress(destination.word);
void callDirect() {
fetchWord();
call();
}
void cc() { callConditional(F().C); }
void cnc() { callConditional(!F().C); }
void cc() { if (callConditional(F().C)) cycles += 6; }
void cnc() { if (callConditional(!F().C)) cycles += 6; }
void cpe() { callConditional(F().P); }
void cpo() { callConditional(!F().P); }
void cpe() { if (callConditional(F().P)) cycles += 6; }
void cpo() { if (callConditional(!F().P)) cycles += 6; }
void cz() { callConditional(F().Z); }
void cnz() { callConditional(!F().Z); }
void cz() { if (callConditional(F().Z)) cycles += 6; }
void cnz() { if (callConditional(!F().Z)) cycles += 6; }
void cm() { callConditional(F().S); }
void cp() { callConditional(!F().S); }
void cm() { if (callConditional(F().S)) cycles += 6; }
void cp() { if (callConditional(!F().S)) cycles += 6; }
// return
void ret() {
popWord(pc);
}
void rc() { if (returnConditional(F().C)) cycles += 6; }
void rnc() { if (returnConditional(!F().C)) cycles += 6; }
void rc() { returnConditional(F().C); }
void rnc() { returnConditional(!F().C); }
void rz() { if (returnConditional(F().Z)) cycles += 6; }
void rnz() { if (returnConditional(!F().Z)) cycles += 6; }
void rz() { returnConditional(F().Z); }
void rnz() { returnConditional(!F().Z); }
void rpe() { if (returnConditional(F().P)) cycles += 6; }
void rpo() { if (returnConditional(!F().P)) cycles += 6; }
void rpe() { returnConditional(F().P); }
void rpo() { returnConditional(!F().P); }
void rm() { returnConditional(F().S); }
void rp() { returnConditional(!F().S); }
void rm() { if (returnConditional(F().S)) cycles += 6; }
void rp() { if (returnConditional(!F().S)) cycles += 6; }
// restart
void rst_0() { restart(0); }
void rst_1() { restart(1); }
void rst_2() { restart(2); }
void rst_3() { restart(3); }
void rst_4() { restart(4); }
void rst_5() { restart(5); }
void rst_6() { restart(6); }
void rst_7() { restart(7); }
void rst_0() { restart(0 << 3); }
void rst_1() { restart(1 << 3); }
void rst_2() { restart(2 << 3); }
void rst_3() { restart(3 << 3); }
void rst_4() { restart(4 << 3); }
void rst_5() { restart(5 << 3); }
void rst_6() { restart(6 << 3); }
void rst_7() { restart(7 << 3); }
// increment and decrement
@ -689,8 +646,8 @@ namespace EightBit {
// control
void ei() { enableInterrupts(); }
void di() { disableInterrupts(); }
void ei() { m_interrupt = true; }
void di() { m_interrupt = false; }
void nop() {}

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
/* 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
/* 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

View File

@ -155,22 +155,12 @@ namespace EightBit {
void postIncrement(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 returnConditional(int condition);
void returnConditionalFlag(int flag);
void jumpConditional(int condition);
void jumpConditionalFlag(int flag);
void callConditional(int condition);
void callConditionalFlag(int flag);
bool jrConditionalFlag(int flag);
bool returnConditionalFlag(int flag);
bool jumpConditionalFlag(int flag);
bool callConditionalFlag(int flag);
void sbc(register16_t& operand, register16_t value);
void adc(register16_t& operand, register16_t value);

View File

@ -8,26 +8,23 @@ EightBit::LR35902::LR35902(Bus& memory)
: IntelProcessor(memory),
m_ime(false),
m_prefixCB(false) {
MEMPTR().word = 0;
}
void EightBit::LR35902::reset() {
Processor::reset();
IntelProcessor::reset();
sp.word = 0xfffe;
di();
}
void EightBit::LR35902::initialise() {
Processor::initialise();
IntelProcessor::initialise();
AF().word = 0xffff;
BC().word = 0xffff;
DE().word = 0xffff;
HL().word = 0xffff;
MEMPTR().word = 0;
m_prefixCB = false;
}
@ -72,89 +69,32 @@ void EightBit::LR35902::postDecrement(uint8_t value) {
#pragma region PC manipulation: call/ret/jp/jr
void EightBit::LR35902::restart(uint8_t address) {
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) {
bool EightBit::LR35902::jrConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
jrConditional(!(F() & ZF));
break;
return jrConditional(!(F() & ZF));
case 1: // Z
jrConditional(F() & ZF);
break;
return jrConditional(F() & ZF);
case 2: // NC
jrConditional(!(F() & CF));
break;
return jrConditional(!(F() & CF));
case 3: // C
jrConditional(F() & CF);
break;
case 4: // PO
case 5: // PE
case 6: // P
case 7: // M
cycles -= 2;
break;
return jrConditional(F() & CF);
}
throw std::logic_error("Unhandled JR conditional");
}
void EightBit::LR35902::jumpConditional(int conditional) {
if (conditional)
pc = MEMPTR();
}
void EightBit::LR35902::jumpConditionalFlag(int flag) {
bool EightBit::LR35902::jumpConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
jumpConditional(!(F() & ZF));
break;
return jumpConditional(!(F() & ZF));
case 1: // Z
jumpConditional(F() & ZF);
break;
return jumpConditional(F() & ZF);
case 2: // NC
jumpConditional(!(F() & CF));
break;
return jumpConditional(!(F() & CF));
case 3: // C
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;
return jumpConditional(F() & CF);
}
}
void EightBit::LR35902::ret() {
popWord(MEMPTR());
pc = MEMPTR();
throw std::logic_error("Unhandled JP conditional");
}
void EightBit::LR35902::reti() {
@ -162,86 +102,35 @@ void EightBit::LR35902::reti() {
ei();
}
void EightBit::LR35902::returnConditional(int condition) {
if (condition) {
ret();
cycles += 3;
}
}
void EightBit::LR35902::returnConditionalFlag(int flag) {
bool EightBit::LR35902::returnConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
returnConditional(!(F() & ZF));
break;
return returnConditional(!(F() & ZF));
case 1: // Z
returnConditional(F() & ZF);
return returnConditional(F() & ZF);
break;
case 2: // NC
returnConditional(!(F() & CF));
return returnConditional(!(F() & CF));
break;
case 3: // C
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
return returnConditional(F() & CF);
break;
}
throw std::logic_error("Unhandled RET conditional");
}
void EightBit::LR35902::callConditional(int condition) {
if (condition) {
call();
cycles += 3;
}
}
void EightBit::LR35902::callConditionalFlag(int flag) {
bool EightBit::LR35902::callConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
callConditional(!(F() & ZF));
break;
return callConditional(!(F() & ZF));
case 1: // Z
callConditional(F() & ZF);
break;
return callConditional(F() & ZF);
case 2: // NC
callConditional(!(F() & CF));
break;
return callConditional(!(F() & CF));
case 3: // C
callConditional(F() & CF);
break;
case 4:
case 5:
case 6:
case 7:
cycles -= 3; // removed from GB
break;
return callConditional(F() & CF);
}
throw std::logic_error("Unhandled CALL conditional");
}
#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++;
break;
case 3: // JR d
jrConditional(true);
cycles += 3;
jr(fetchByte());
cycles += 4;
break;
default: // JR cc,d
jrConditionalFlag(y - 4);
cycles += 2;
default: { // JR cc,d
auto condition = y - 4;
if (y < 4) {
if (jrConditionalFlag(condition))
cycles++;
cycles += 2;
}
}
break;
}
break;
@ -786,8 +680,42 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
case 3:
switch (z) {
case 0: // Conditional return
returnConditionalFlag(y);
cycles += 2;
if (y < 4) {
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;
case 1: // POP & various ops
switch (q) {
@ -817,8 +745,34 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
}
break;
case 2: // Conditional jump
jumpConditionalFlag(y);
cycles += 3;
if (y < 4) {
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;
case 3: // Assorted operations
switch (y) {

View File

@ -24,8 +24,8 @@ namespace EightBit {
Signal<Z80> ExecutingInstruction;
void disableInterrupts();
void enableInterrupts();
void di();
void ei();
int interruptMaskable(uint8_t value) { return interrupt(true, value); }
int interruptMaskable() { return interruptMaskable(0); }
@ -126,19 +126,7 @@ namespace EightBit {
int fetchExecute() {
M1() = true;
return execute(fetchByteExecute());
}
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();
return execute(fetchByte());
}
void incrementRefresh() {
@ -180,7 +168,7 @@ namespace EightBit {
return ALT_HL().low;
case 6:
if (m_prefixDD || m_prefixFD) {
m_displacement = fetchByteData();
m_displacement = fetchByte();
return DISPLACED();
}
m_memory.ADDRESS() = HL();
@ -330,24 +318,13 @@ namespace EightBit {
void postIncrement(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 reti();
void returnConditional(int condition);
void returnConditionalFlag(int flag);
void jumpConditional(int condition);
void jumpConditionalFlag(int flag);
virtual void call() override;
void callConditional(int condition);
void callConditionalFlag(int flag);
bool jrConditionalFlag(int flag);
bool returnConditionalFlag(int flag);
bool jumpConditionalFlag(int flag);
bool callConditionalFlag(int flag);
void sbc(register16_t& operand, register16_t value);
void adc(register16_t& operand, register16_t value);

View File

@ -25,7 +25,7 @@ EightBit::Z80::Z80(Memory& memory, InputOutput& ports)
void EightBit::Z80::reset() {
IntelProcessor::reset();
IFF1() = IFF2() = false;
di();
}
void EightBit::Z80::initialise() {
@ -63,11 +63,11 @@ void EightBit::Z80::initialise() {
#pragma region Interrupt routines
void EightBit::Z80::disableInterrupts() {
void EightBit::Z80::di() {
IFF1() = IFF2() = false;
}
void EightBit::Z80::enableInterrupts() {
void EightBit::Z80::ei() {
IFF1() = IFF2() = true;
}
@ -75,7 +75,7 @@ int EightBit::Z80::interrupt(bool maskable, uint8_t value) {
cycles = 0;
if (!maskable || (maskable && IFF1())) {
if (maskable) {
disableInterrupts();
di();
switch (IM()) {
case 0:
M1() = true;
@ -93,7 +93,7 @@ int EightBit::Z80::interrupt(bool maskable, uint8_t value) {
break;
}
} else {
IFF1() = 0;
IFF1() = false;
restart(0x66);
cycles += 13;
}
@ -163,87 +163,48 @@ void EightBit::Z80::postDecrement(uint8_t value) {
#pragma region PC manipulation: call/ret/jp/jr
void EightBit::Z80::restart(uint8_t address) {
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) {
bool EightBit::Z80::jrConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
jrConditional(!(F() & ZF));
break;
return jrConditional(!(F() & ZF));
case 1: // Z
jrConditional(F() & ZF);
break;
return jrConditional(F() & ZF);
case 2: // NC
jrConditional(!(F() & CF));
break;
return jrConditional(!(F() & CF));
case 3: // C
jrConditional(F() & CF);
break;
return jrConditional(F() & CF);
case 4: // PO
jrConditional(!(F() & PF));
break;
return jrConditional(!(F() & PF));
case 5: // PE
jrConditional(F() & PF);
break;
return jrConditional(F() & PF);
case 6: // P
jrConditional(!(F() & SF));
break;
return jrConditional(!(F() & SF));
case 7: // M
jrConditional(F() & SF);
break;
return jrConditional(F() & SF);
}
throw std::logic_error("Unhandled JR conditional");
}
void EightBit::Z80::jumpConditional(int conditional) {
if (conditional)
pc = MEMPTR();
}
void EightBit::Z80::jumpConditionalFlag(int flag) {
bool EightBit::Z80::jumpConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
jumpConditional(!(F() & ZF));
break;
return jumpConditional(!(F() & ZF));
case 1: // Z
jumpConditional(F() & ZF);
break;
return jumpConditional(F() & ZF);
case 2: // NC
jumpConditional(!(F() & CF));
break;
return jumpConditional(!(F() & CF));
case 3: // C
jumpConditional(F() & CF);
break;
return jumpConditional(F() & CF);
case 4: // PO
jumpConditional(!(F() & PF));
break;
return jumpConditional(!(F() & PF));
case 5: // PE
jumpConditional(F() & PF);
break;
return jumpConditional(F() & PF);
case 6: // P
jumpConditional(!(F() & SF));
break;
return jumpConditional(!(F() & SF));
case 7: // M
jumpConditional(F() & SF);
break;
return jumpConditional(F() & SF);
}
}
void EightBit::Z80::ret() {
popWord(MEMPTR());
pc = MEMPTR();
throw std::logic_error("Unhandled JP conditional");
}
void EightBit::Z80::retn() {
@ -255,79 +216,48 @@ void EightBit::Z80::reti() {
retn();
}
void EightBit::Z80::returnConditional(int condition) {
if (condition) {
ret();
cycles += 6;
}
}
void EightBit::Z80::returnConditionalFlag(int flag) {
bool EightBit::Z80::returnConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
returnConditional(!(F() & ZF));
break;
return returnConditional(!(F() & ZF));
case 1: // Z
returnConditional(F() & ZF);
break;
return returnConditional(F() & ZF);
case 2: // NC
returnConditional(!(F() & CF));
break;
return returnConditional(!(F() & CF));
case 3: // C
returnConditional(F() & CF);
break;
return returnConditional(F() & CF);
case 4: // PO
returnConditional(!(F() & PF));
break;
return returnConditional(!(F() & PF));
case 5: // PE
returnConditional(F() & PF);
break;
return returnConditional(F() & PF);
case 6: // P
returnConditional(!(F() & SF));
break;
return returnConditional(!(F() & SF));
case 7: // M
returnConditional(F() & SF);
break;
return returnConditional(F() & SF);
}
throw std::logic_error("Unhandled RET conditional");
}
void EightBit::Z80::call() {
IntelProcessor::call();
cycles += 7;
}
void EightBit::Z80::callConditional(int condition) {
if (condition)
call();
}
void EightBit::Z80::callConditionalFlag(int flag) {
bool EightBit::Z80::callConditionalFlag(int flag) {
switch (flag) {
case 0: // NZ
callConditional(!(F() & ZF));
break;
return callConditional(!(F() & ZF));
case 1: // Z
callConditional(F() & ZF);
break;
return callConditional(F() & ZF);
case 2: // NC
callConditional(!(F() & CF));
break;
return callConditional(!(F() & CF));
case 3: // C
callConditional(F() & CF);
break;
return callConditional(F() & CF);
case 4: // PO
callConditional(!(F() & PF));
break;
return callConditional(!(F() & PF));
case 5: // PE
callConditional(F() & PF);
break;
return callConditional(F() & PF);
case 6: // P
callConditional(!(F() & SF));
break;
return callConditional(!(F() & SF));
case 7: // M
callConditional(F() & SF);
break;
return callConditional(F() & SF);
}
throw std::logic_error("Unhandled CALL conditional");
}
#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;
break;
case 2: // DJNZ d
jrConditional(--B());
if (jrConditional(--B()))
cycles += 5;
cycles += 8;
break;
case 3: // JR d
jrConditional(true);
cycles += 7;
jr(fetchByte());
cycles += 12;
break;
default: // JR cc,d
jrConditionalFlag(y - 4);
if (jrConditionalFlag(y - 4))
cycles += 5;
cycles += 5;
break;
}
@ -1347,7 +1279,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 7;
break;
case 6: { // 8-bit load immediate
R(y) = fetchByteData(); // LD r,n
R(y) = fetchByte(); // LD r,n
cycles += 7;
if (y == 6)
cycles += 3;
@ -1455,7 +1387,8 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
case 3:
switch (z) {
case 0: // Conditional return
returnConditionalFlag(y);
if (returnConditionalFlag(y))
cycles += 6;
cycles += 5;
break;
case 1: // POP & various ops
@ -1486,7 +1419,6 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
}
break;
case 2: // Conditional jump
fetchWord();
jumpConditionalFlag(y);
cycles += 10;
break;
@ -1494,17 +1426,17 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
switch (y) {
case 0: // JP nn
fetchWord();
pc = MEMPTR();
jump();
cycles += 10;
break;
case 1: // CB prefix
m_prefixCB = true;
if (m_prefixDD || m_prefixFD)
m_displacement = fetchByteData();
m_displacement = fetchByte();
fetchExecute();
break;
case 2: // OUT (n),A
m_memory.ADDRESS().low = fetchByteData();
m_memory.ADDRESS().low = fetchByte();
m_memory.ADDRESS().high = A();
MEMPTR() = m_memory.ADDRESS();
m_memory.placeDATA(A());
@ -1513,7 +1445,7 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 11;
break;
case 3: // IN A,(n)
m_memory.ADDRESS().low = fetchByteData();
m_memory.ADDRESS().low = fetchByte();
m_memory.ADDRESS().high = A();
MEMPTR() = m_memory.ADDRESS();
readPort();
@ -1530,18 +1462,18 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
cycles += 4;
break;
case 6: // DI
disableInterrupts();
di();
cycles += 4;
break;
case 7: // EI
enableInterrupts();
ei();
cycles += 4;
break;
}
break;
case 4: // Conditional call: CALL cc[y], nn
fetchWord();
callConditionalFlag(y);
if (callConditionalFlag(y))
cycles += 7;
cycles += 10;
break;
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
switch (y) {
case 0: // ADD A,n
add(A(), fetchByteData());
add(A(), fetchByte());
break;
case 1: // ADC A,n
adc(A(), fetchByteData());
adc(A(), fetchByte());
break;
case 2: // SUB n
sub(A(), fetchByteData());
sub(A(), fetchByte());
break;
case 3: // SBC A,n
sbc(A(), fetchByteData());
sbc(A(), fetchByte());
break;
case 4: // AND n
andr(A(), fetchByteData());
andr(A(), fetchByte());
break;
case 5: // XOR n
xorr(A(), fetchByteData());
xorr(A(), fetchByte());
break;
case 6: // OR n
orr(A(), fetchByteData());
orr(A(), fetchByte());
break;
case 7: // CP n
compare(fetchByteData());
compare(fetchByte());
break;
}
cycles += 7;

View File

@ -6,8 +6,6 @@ namespace EightBit {
class IntelProcessor : public Processor
{
public:
virtual ~IntelProcessor();
register16_t& MEMPTR() { return m_memptr; }
virtual void initialise();
@ -42,11 +40,60 @@ namespace EightBit {
Processor::fetchWord(MEMPTR());
}
virtual void call() {
pushWord(pc);
//
void jump() {
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:
register16_t m_memptr;
};

View File

@ -6,15 +6,11 @@ EightBit::IntelProcessor::IntelProcessor(Memory& memory)
MEMPTR().word = 0;
}
EightBit::IntelProcessor::~IntelProcessor() {
}
void EightBit::IntelProcessor::initialise() {
Processor::initialise();
MEMPTR().word = 0;
}
void EightBit::IntelProcessor::push(uint8_t value) {
m_memory.ADDRESS().word = --sp.word;
m_memory.reference() = value;