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& L() { return HL().low; }
register16_t& MEMPTR() { return m_memptr; }
virtual void reset();
virtual void initialise();
@ -75,6 +77,8 @@ namespace EightBit {
bool m_ime;
register16_t m_memptr;
bool m_prefixCB;
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_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
register16_t fetchWord() {
register16_t returned;
Processor::fetchWord(returned);
return returned;
void fetchWord() {
Processor::fetchWord(MEMPTR());
}
int fetchExecute() {
@ -180,28 +182,22 @@ namespace EightBit {
void jumpConditional(int condition);
void jumpConditionalFlag(int flag);
void call(uint16_t address);
void callConditional(uint16_t address, int condition);
void callConditionalFlag(uint16_t address, int flag);
void call();
void callConditional(int condition);
void callConditionalFlag(int flag);
uint16_t sbc(uint16_t value);
uint16_t adc(uint16_t value);
void sbc(register16_t& operand, register16_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 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 add(uint8_t& operand, uint8_t value, int carry = 0);
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 anda(uint8_t value);
void xora(uint8_t value);
void ora(uint8_t value);
void xorr(uint8_t& operand, uint8_t value);
void orr(uint8_t& operand, uint8_t value);
void compare(uint8_t value);
void rlca();

View File

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