mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-23 00:29:47 +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& 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();
|
||||||
|
@ -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());
|
||||||
|
Loading…
Reference in New Issue
Block a user