mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-22 09:30:32 +00:00
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:
parent
93bac42547
commit
838580cc3d
@ -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();
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user