More changes to bring LR35902 in line with the Z80 implementation.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-06-09 16:01:12 +01:00
parent 93bac42547
commit 838580cc3d
2 changed files with 106 additions and 145 deletions

View File

@ -64,6 +64,8 @@ namespace EightBit {
uint8_t& H() { return HL().high; } uint8_t& H() { return HL().high; }
uint8_t& L() { return HL().low; } uint8_t& L() { return HL().low; }
register16_t& MEMPTR() { return m_memptr; }
virtual void reset(); virtual void reset();
virtual void initialise(); virtual void initialise();
@ -75,6 +77,8 @@ namespace EightBit {
bool m_ime; bool m_ime;
register16_t m_memptr;
bool m_prefixCB; bool m_prefixCB;
bool m_stopped; bool m_stopped;
@ -82,10 +86,8 @@ namespace EightBit {
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } }; std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } }; std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
register16_t fetchWord() { void fetchWord() {
register16_t returned; Processor::fetchWord(MEMPTR());
Processor::fetchWord(returned);
return returned;
} }
int fetchExecute() { int fetchExecute() {
@ -180,28 +182,22 @@ namespace EightBit {
void jumpConditional(int condition); void jumpConditional(int condition);
void jumpConditionalFlag(int flag); void jumpConditionalFlag(int flag);
void call(uint16_t address); void call();
void callConditional(uint16_t address, int condition); void callConditional(int condition);
void callConditionalFlag(uint16_t address, int flag); void callConditionalFlag(int flag);
uint16_t sbc(uint16_t value); void sbc(register16_t& operand, register16_t value);
uint16_t adc(uint16_t value); void adc(register16_t& operand, register16_t value);
uint16_t add(uint16_t value); void add(register16_t& operand, register16_t value);
void sub(uint8_t& operand, uint8_t value, bool carry); void add(uint8_t& operand, uint8_t value, int carry = 0);
void sub(uint8_t& operand, uint8_t value);
void sbc(uint8_t& operand, uint8_t value);
void add(uint8_t& operand, uint8_t value, bool carry);
void add(uint8_t& operand, uint8_t value);
void adc(uint8_t& operand, uint8_t value); void adc(uint8_t& operand, uint8_t value);
void sub(uint8_t& operand, uint8_t value, int carry = 0);
void sbc(uint8_t& operand, uint8_t value);
void andr(uint8_t& operand, uint8_t value); void andr(uint8_t& operand, uint8_t value);
void xorr(uint8_t& operand, uint8_t value);
void anda(uint8_t value); void orr(uint8_t& operand, uint8_t value);
void xora(uint8_t value);
void ora(uint8_t value);
void compare(uint8_t value); void compare(uint8_t value);
void rlca(); void rlca();

View File

@ -8,6 +8,7 @@ EightBit::LR35902::LR35902(Bus& memory)
: Processor(memory), : Processor(memory),
m_ime(false), m_ime(false),
m_prefixCB(false) { m_prefixCB(false) {
MEMPTR().word = 0;
} }
void EightBit::LR35902::reset() { void EightBit::LR35902::reset() {
@ -25,6 +26,8 @@ void EightBit::LR35902::initialise() {
DE().word = 0xffff; DE().word = 0xffff;
HL().word = 0xffff; HL().word = 0xffff;
MEMPTR().word = 0;
m_prefixCB = false; m_prefixCB = false;
} }
@ -107,11 +110,8 @@ void EightBit::LR35902::jrConditionalFlag(int flag) {
} }
void EightBit::LR35902::jumpConditional(int conditional) { void EightBit::LR35902::jumpConditional(int conditional) {
auto address = fetchWord(); if (conditional)
if (conditional) { pc = MEMPTR();
pc = address;
cycles++;
}
} }
void EightBit::LR35902::jumpConditionalFlag(int flag) { void EightBit::LR35902::jumpConditionalFlag(int flag) {
@ -133,7 +133,8 @@ void EightBit::LR35902::jumpConditionalFlag(int flag) {
cycles--; // Giving 8 cycles cycles--; // Giving 8 cycles
break; break;
case 5: // GB: LD (nn),A case 5: // GB: LD (nn),A
m_memory.ADDRESS() = fetchWord(); fetchWord();
m_memory.ADDRESS() = MEMPTR();
m_memory.reference() = A(); m_memory.reference() = A();
cycles++; // Giving 16 cycles cycles++; // Giving 16 cycles
break; break;
@ -143,7 +144,8 @@ void EightBit::LR35902::jumpConditionalFlag(int flag) {
cycles--; // 8 cycles cycles--; // 8 cycles
break; break;
case 7: // GB: LD A,(nn) case 7: // GB: LD A,(nn)
m_memory.ADDRESS() = fetchWord(); fetchWord();
m_memory.ADDRESS() = MEMPTR();
A() = m_memory.reference(); A() = m_memory.reference();
cycles++; // Giving 16 cycles cycles++; // Giving 16 cycles
break; break;
@ -151,7 +153,8 @@ void EightBit::LR35902::jumpConditionalFlag(int flag) {
} }
void EightBit::LR35902::ret() { void EightBit::LR35902::ret() {
popWord(pc); popWord(MEMPTR());
pc = MEMPTR();
} }
void EightBit::LR35902::reti() { void EightBit::LR35902::reti() {
@ -211,31 +214,31 @@ void EightBit::LR35902::returnConditionalFlag(int flag) {
} }
} }
void EightBit::LR35902::call(uint16_t address) { void EightBit::LR35902::call() {
pushWord(pc); pushWord(pc);
pc.word = address; pc = MEMPTR();
} }
void EightBit::LR35902::callConditional(uint16_t address, int condition) { void EightBit::LR35902::callConditional(int condition) {
if (condition) { if (condition) {
call(address); call();
cycles += 3; cycles += 3;
} }
} }
void EightBit::LR35902::callConditionalFlag(uint16_t address, int flag) { void EightBit::LR35902::callConditionalFlag(int flag) {
switch (flag) { switch (flag) {
case 0: // NZ case 0: // NZ
callConditional(address, !(F() & ZF)); callConditional(!(F() & ZF));
break; break;
case 1: // Z case 1: // Z
callConditional(address, F() & ZF); callConditional(F() & ZF);
break; break;
case 2: // NC case 2: // NC
callConditional(address, !(F() & CF)); callConditional(!(F() & CF));
break; break;
case 3: // C case 3: // C
callConditional(address, F() & CF); callConditional(F() & CF);
break; break;
case 4: case 4:
case 5: case 5:
@ -250,143 +253,100 @@ void EightBit::LR35902::callConditionalFlag(uint16_t address, int flag) {
#pragma region 16-bit arithmetic #pragma region 16-bit arithmetic
uint16_t EightBit::LR35902::sbc(uint16_t value) { void EightBit::LR35902::sbc(register16_t& operand, register16_t value) {
auto hl = RP(HL_IDX); auto before = operand;
auto high = hl.high; auto result = before.word - value.word - (F() & CF);
auto highValue = Memory::highByte(value); operand.word = result;
auto applyCarry = F() & CF;
uint32_t result = (int)hl.word - (int)value;
if (applyCarry)
--result;
auto highResult = Memory::highByte(result);
adjustZero(result);
adjustHalfCarrySub(high, highValue, highResult);
clearFlag(ZF, operand.word);
adjustHalfCarrySub(before.high, value.high, operand.high);
setFlag(NF); setFlag(NF);
setFlag(CF, result & Bit16); setFlag(CF, result & Bit16);
return result;
} }
uint16_t EightBit::LR35902::adc(uint16_t value) { void EightBit::LR35902::adc(register16_t& operand, register16_t value) {
auto hl = RP(HL_IDX); auto before = operand;
auto high = hl.high; auto result = before.word + value.word + (F() & CF);
auto highValue = Memory::highByte(value); operand.word = result;
auto applyCarry = F() & CF;
uint32_t result = (int)hl.word + (int)value; clearFlag(ZF, result);
if (applyCarry) adjustHalfCarryAdd(before.high, value.high, operand.high);
++result; clearFlag(NF);
auto highResult = Memory::highByte(result); setFlag(CF, result & Bit16);
}
adjustZero(result); void EightBit::LR35902::add(register16_t& operand, register16_t value) {
adjustHalfCarryAdd(high, highValue, highResult);
auto before = operand;
auto result = before.word + value.word;
operand.word = result;
clearFlag(NF); clearFlag(NF);
setFlag(CF, result & Bit16); setFlag(CF, result & Bit16);
adjustHalfCarryAdd(before.high, value.high, operand.high);
return result;
}
uint16_t EightBit::LR35902::add(uint16_t value) {
auto hl = RP(HL_IDX);
auto high = hl.high;
auto highValue = Memory::highByte(value);
uint32_t result = (int)hl.word + (int)value;
auto highResult = Memory::highByte(result);
clearFlag(NF);
setFlag(CF, result & Bit16);
adjustHalfCarryAdd(high, highValue, highResult);
return result;
} }
#pragma endregion 16-bit arithmetic #pragma endregion 16-bit arithmetic
#pragma region ALU #pragma region ALU
void EightBit::LR35902::sub(uint8_t& operand, uint8_t value, bool carry) { void EightBit::LR35902::add(uint8_t& operand, uint8_t value, int carry) {
auto before = operand; register16_t result;
result.word = operand + value + carry;
uint16_t result = before - value; adjustHalfCarryAdd(operand, value, result.low);
if (carry && (F() & CF))
--result;
operand = Memory::lowByte(result); operand = result.low;
adjustZero(operand);
adjustHalfCarrySub(before, value, result);
setFlag(NF);
setFlag(CF, result & Bit8);
}
void EightBit::LR35902::sbc(uint8_t& operand, uint8_t value) {
sub(operand, value, true);
}
void EightBit::LR35902::sub(uint8_t& operand, uint8_t value) {
sub(operand, value, false);
}
void EightBit::LR35902::add(uint8_t& operand, uint8_t value, bool carry) {
auto before = operand;
uint16_t result = before + value;
if (carry && (F() & CF))
++result;
operand = Memory::lowByte(result);
adjustZero(operand);
adjustHalfCarryAdd(before, value, result);
clearFlag(NF); clearFlag(NF);
setFlag(CF, result & Bit8); setFlag(CF, result.word & Bit8);
} }
void EightBit::LR35902::adc(uint8_t& operand, uint8_t value) { void EightBit::LR35902::adc(uint8_t& operand, uint8_t value) {
add(operand, value, true); add(operand, value, F() & CF);
} }
void EightBit::LR35902::add(uint8_t& operand, uint8_t value) { void EightBit::LR35902::sub(uint8_t& operand, uint8_t value, int carry) {
add(operand, value, false);
register16_t result;
result.word = operand - value - carry;
adjustHalfCarrySub(operand, value, result.low);
operand = result.low;
setFlag(NF);
setFlag(CF, result.word & Bit8);
} }
// void EightBit::LR35902::sbc(uint8_t& operand, uint8_t value) {
sub(operand, value, F() & CF);
}
void EightBit::LR35902::andr(uint8_t& operand, uint8_t value) { void EightBit::LR35902::andr(uint8_t& operand, uint8_t value) {
operand &= value;
setFlag(HC); setFlag(HC);
clearFlag(CF | NF); clearFlag(CF | NF);
operand &= value;
adjustZero(operand); adjustZero(operand);
} }
void EightBit::LR35902::anda(uint8_t value) { void EightBit::LR35902::xorr(uint8_t& operand, uint8_t value) {
andr(A(), value); operand ^= value;
clearFlag(HC | CF | NF);
adjustZero(operand);
} }
void EightBit::LR35902::xora(uint8_t value) { void EightBit::LR35902::orr(uint8_t& operand, uint8_t value) {
operand |= value;
clearFlag(HC | CF | NF); clearFlag(HC | CF | NF);
A() ^= value; adjustZero(operand);
adjustZero(A());
}
void EightBit::LR35902::ora(uint8_t value) {
clearFlag(HC | CF | NF);
A() |= value;
adjustZero(A());
} }
void EightBit::LR35902::compare(uint8_t value) { void EightBit::LR35902::compare(uint8_t value) {
@ -652,7 +612,8 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
cycles++; cycles++;
break; break;
case 1: // GB: LD (nn),SP case 1: // GB: LD (nn),SP
m_memory.setWord(fetchWord().word, sp); fetchWord();
m_memory.setWord(MEMPTR().word, sp);
cycles += 5; cycles += 5;
break; break;
case 2: // GB: STOP case 2: // GB: STOP
@ -672,11 +633,12 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
case 1: // 16-bit load immediate/add case 1: // 16-bit load immediate/add
switch (q) { switch (q) {
case 0: // LD rp,nn case 0: // LD rp,nn
RP(p) = fetchWord(); fetchWord();
RP(p) = MEMPTR();
cycles += 3; cycles += 3;
break; break;
case 1: // ADD HL,rp case 1: // ADD HL,rp
RP(HL_IDX).word = add(RP(p).word); add(HL(), RP(p));
cycles += 2; cycles += 2;
break; break;
} }
@ -808,13 +770,13 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
sbc(A(), R(z)); sbc(A(), R(z));
break; break;
case 4: // AND r case 4: // AND r
anda(R(z)); andr(A(), R(z));
break; break;
case 5: // XOR r case 5: // XOR r
xora(R(z)); xorr(A(), R(z));
break; break;
case 6: // OR r case 6: // OR r
ora(R(z)); orr(A(), R(z));
break; break;
case 7: // CP r case 7: // CP r
compare(R(z)); compare(R(z));
@ -864,7 +826,8 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
case 3: // Assorted operations case 3: // Assorted operations
switch (y) { switch (y) {
case 0: // JP nn case 0: // JP nn
pc = fetchWord(); fetchWord();
pc = MEMPTR();
cycles += 4; cycles += 4;
break; break;
case 1: // CB prefix case 1: // CB prefix
@ -882,7 +845,8 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
} }
break; break;
case 4: // Conditional call: CALL cc[y], nn case 4: // Conditional call: CALL cc[y], nn
callConditionalFlag(fetchWord().word, y); fetchWord();
callConditionalFlag(y);
cycles += 3; cycles += 3;
break; break;
case 5: // PUSH & various ops case 5: // PUSH & various ops
@ -894,7 +858,8 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
case 1: case 1:
switch (p) { switch (p) {
case 0: // CALL nn case 0: // CALL nn
callConditional(fetchWord().word, true); fetchWord();
callConditional(true);
cycles += 3; cycles += 3;
break; break;
} }
@ -915,13 +880,13 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
sbc(A(), fetchByte()); sbc(A(), fetchByte());
break; break;
case 4: // AND n case 4: // AND n
anda(fetchByte()); andr(A(), fetchByte());
break; break;
case 5: // XOR n case 5: // XOR n
xora(fetchByte()); xorr(A(), fetchByte());
break; break;
case 6: // OR n case 6: // OR n
ora(fetchByte()); orr(A(), fetchByte());
break; break;
case 7: // CP n case 7: // CP n
compare(fetchByte()); compare(fetchByte());