mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-07-27 09:29:22 +00:00
Bring the various IntelProcessor derived processors a little closer together.
Signed-off-by: Adrian.Conlon <adrian.conlon@arup.com>
This commit is contained in:
parent
758574007d
commit
36fbee35fb
@ -107,9 +107,8 @@ namespace EightBit {
|
||||
|
||||
//
|
||||
|
||||
void compare(uint8_t value) {
|
||||
auto check = A();
|
||||
sub(check, value);
|
||||
void compare(uint8_t& f, uint8_t check, uint8_t value) {
|
||||
subtract(f, check, value);
|
||||
}
|
||||
|
||||
void anda(uint8_t value) {
|
||||
@ -154,22 +153,21 @@ namespace EightBit {
|
||||
HL().word = sum;
|
||||
}
|
||||
|
||||
void sub(uint8_t& operand, uint8_t value, int carry = 0) {
|
||||
auto& f = F();
|
||||
register16_t difference;
|
||||
difference.word = operand - value - carry;
|
||||
adjustAuxiliaryCarrySub(f, operand, value, difference.word);
|
||||
operand = difference.low;
|
||||
setFlag(f, CF, difference.word & Bit8);
|
||||
void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0) {
|
||||
|
||||
register16_t result;
|
||||
result.word = operand - value - carry;
|
||||
|
||||
adjustAuxiliaryCarrySub(f, operand, value, result.word);
|
||||
|
||||
operand = result.low;
|
||||
|
||||
setFlag(f, CF, result.word & Bit8);
|
||||
adjustSZP<Intel8080>(f, operand);
|
||||
}
|
||||
|
||||
void sub(uint8_t value, int carry = 0) {
|
||||
sub(A(), value, carry);
|
||||
}
|
||||
|
||||
void sbb(uint8_t value) {
|
||||
sub(value, F() & CF);
|
||||
subtract(F(), A(), value, F() & CF);
|
||||
}
|
||||
|
||||
void mov_m_r(uint8_t value) {
|
||||
@ -499,17 +497,17 @@ namespace EightBit {
|
||||
|
||||
// subtract
|
||||
|
||||
void sub_a() { sub(A()); }
|
||||
void sub_b() { sub(B()); }
|
||||
void sub_c() { sub(C()); }
|
||||
void sub_d() { sub(D()); }
|
||||
void sub_e() { sub(E()); }
|
||||
void sub_h() { sub(H()); }
|
||||
void sub_l() { sub(L()); }
|
||||
void sub_a() { subtract(F(), A(), A()); }
|
||||
void sub_b() { subtract(F(), A(), B()); }
|
||||
void sub_c() { subtract(F(), A(), C()); }
|
||||
void sub_d() { subtract(F(), A(), D()); }
|
||||
void sub_e() { subtract(F(), A(), E()); }
|
||||
void sub_h() { subtract(F(), A(), H()); }
|
||||
void sub_l() { subtract(F(), A(), L()); }
|
||||
|
||||
void sub_m() {
|
||||
m_memory.ADDRESS() = HL();
|
||||
sub(m_memory.reference());
|
||||
subtract(F(), A(), m_memory.reference());
|
||||
}
|
||||
|
||||
void sbb_a() { sbb(A()); }
|
||||
@ -530,7 +528,7 @@ namespace EightBit {
|
||||
}
|
||||
|
||||
void sui() {
|
||||
sub(fetchByte());
|
||||
subtract(F(), A(), fetchByte());
|
||||
}
|
||||
|
||||
// logical
|
||||
@ -580,20 +578,20 @@ namespace EightBit {
|
||||
|
||||
void ori() { ora(fetchByte()); }
|
||||
|
||||
void cmp_a() { compare(A()); }
|
||||
void cmp_b() { compare(B()); }
|
||||
void cmp_c() { compare(C()); }
|
||||
void cmp_d() { compare(D()); }
|
||||
void cmp_e() { compare(E()); }
|
||||
void cmp_h() { compare(H()); }
|
||||
void cmp_l() { compare(L()); }
|
||||
void cmp_a() { compare(F(), A(), A()); }
|
||||
void cmp_b() { compare(F(), A(), B()); }
|
||||
void cmp_c() { compare(F(), A(), C()); }
|
||||
void cmp_d() { compare(F(), A(), D()); }
|
||||
void cmp_e() { compare(F(), A(), E()); }
|
||||
void cmp_h() { compare(F(), A(), H()); }
|
||||
void cmp_l() { compare(F(), A(), L()); }
|
||||
|
||||
void cmp_m() {
|
||||
m_memory.ADDRESS() = HL();
|
||||
compare(m_memory.reference());
|
||||
compare(F(), A(), m_memory.reference());
|
||||
}
|
||||
|
||||
void cpi() { compare(fetchByte()); }
|
||||
void cpi() { compare(F(), A(), fetchByte()); }
|
||||
|
||||
// rotate
|
||||
|
||||
|
@ -108,7 +108,7 @@ namespace EightBit {
|
||||
return execute(fetchByte());
|
||||
}
|
||||
|
||||
uint8_t& R(int r) {
|
||||
uint8_t& R(int r, uint8_t& a) {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return B();
|
||||
@ -126,7 +126,7 @@ namespace EightBit {
|
||||
m_memory.ADDRESS() = HL();
|
||||
return m_memory.reference();
|
||||
case 7:
|
||||
return A();
|
||||
return a;
|
||||
}
|
||||
throw std::logic_error("Unhandled registry mechanism");
|
||||
}
|
||||
@ -157,6 +157,8 @@ namespace EightBit {
|
||||
setFlag(f, HC, calculateHalfCarrySub(before, value, calculation));
|
||||
}
|
||||
|
||||
static void subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
|
||||
|
||||
void executeCB(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
|
||||
@ -165,43 +167,41 @@ namespace EightBit {
|
||||
|
||||
void reti();
|
||||
|
||||
bool jrConditionalFlag(int flag);
|
||||
bool returnConditionalFlag(int flag);
|
||||
bool jumpConditionalFlag(int flag);
|
||||
bool callConditionalFlag(int flag);
|
||||
bool jrConditionalFlag(uint8_t& f, int flag);
|
||||
bool returnConditionalFlag(uint8_t& f, int flag);
|
||||
bool jumpConditionalFlag(uint8_t& f, int flag);
|
||||
bool callConditionalFlag(uint8_t& f, int flag);
|
||||
|
||||
void sbc(register16_t& operand, register16_t value);
|
||||
void adc(register16_t& operand, register16_t value);
|
||||
void sbc(uint8_t& f, register16_t& operand, register16_t value);
|
||||
void adc(uint8_t& f, register16_t& operand, register16_t value);
|
||||
void add(uint8_t& f, register16_t& operand, register16_t value);
|
||||
|
||||
void add(register16_t& operand, register16_t value);
|
||||
static void add(uint8_t& f, uint8_t& operand, uint8_t value, int carry = 0);
|
||||
static void adc(uint8_t& f, uint8_t& operand, uint8_t value);
|
||||
static void sbc(uint8_t& f, uint8_t& operand, uint8_t value);
|
||||
static void andr(uint8_t& f, uint8_t& operand, uint8_t value);
|
||||
static void xorr(uint8_t& f, uint8_t& operand, uint8_t value);
|
||||
static void orr(uint8_t& f, uint8_t& operand, uint8_t value);
|
||||
static void compare(uint8_t& f, uint8_t check, 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 xorr(uint8_t& operand, uint8_t value);
|
||||
void orr(uint8_t& operand, uint8_t value);
|
||||
void compare(uint8_t value);
|
||||
static void rlc(uint8_t& f, uint8_t& operand);
|
||||
static void rrc(uint8_t& f, uint8_t& operand);
|
||||
static void rl(uint8_t& f, uint8_t& operand);
|
||||
static void rr(uint8_t& f, uint8_t& operand);
|
||||
static void sla(uint8_t& f, uint8_t& operand);
|
||||
static void sra(uint8_t& f, uint8_t& operand);
|
||||
static void srl(uint8_t& f, uint8_t& operand);
|
||||
|
||||
void rlc(uint8_t& operand);
|
||||
void rrc(uint8_t& operand);
|
||||
void rl(uint8_t& operand);
|
||||
void rr(uint8_t& operand);
|
||||
void sla(uint8_t& operand);
|
||||
void sra(uint8_t& operand);
|
||||
void srl(uint8_t& operand);
|
||||
static void bit(uint8_t& f, int n, uint8_t& operand);
|
||||
static void res(int n, uint8_t& operand);
|
||||
static void set(int n, uint8_t& operand);
|
||||
|
||||
void bit(int n, uint8_t& operand);
|
||||
void res(int n, uint8_t& operand);
|
||||
void set(int nit, uint8_t& operand);
|
||||
static void daa(uint8_t& a, uint8_t& f);
|
||||
|
||||
void daa();
|
||||
static void scf(uint8_t& a, uint8_t& f);
|
||||
static void ccf(uint8_t& a, uint8_t& f);
|
||||
static void cpl(uint8_t& a, uint8_t& f);
|
||||
|
||||
void scf();
|
||||
void ccf();
|
||||
void cpl();
|
||||
|
||||
void swap(uint8_t& operand);
|
||||
void swap(uint8_t& f, uint8_t& operand);
|
||||
};
|
||||
}
|
@ -67,30 +67,30 @@ void EightBit::LR35902::postDecrement(uint8_t& f, uint8_t value) {
|
||||
|
||||
#pragma region PC manipulation: call/ret/jp/jr
|
||||
|
||||
bool EightBit::LR35902::jrConditionalFlag(int flag) {
|
||||
bool EightBit::LR35902::jrConditionalFlag(uint8_t& f, int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
return jrConditional(!(F() & ZF));
|
||||
return jrConditional(!(f & ZF));
|
||||
case 1: // Z
|
||||
return jrConditional(F() & ZF);
|
||||
return jrConditional(f & ZF);
|
||||
case 2: // NC
|
||||
return jrConditional(!(F() & CF));
|
||||
return jrConditional(!(f & CF));
|
||||
case 3: // C
|
||||
return jrConditional(F() & CF);
|
||||
return jrConditional(f & CF);
|
||||
}
|
||||
throw std::logic_error("Unhandled JR conditional");
|
||||
}
|
||||
|
||||
bool EightBit::LR35902::jumpConditionalFlag(int flag) {
|
||||
bool EightBit::LR35902::jumpConditionalFlag(uint8_t& f, int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
return jumpConditional(!(F() & ZF));
|
||||
return jumpConditional(!(f & ZF));
|
||||
case 1: // Z
|
||||
return jumpConditional(F() & ZF);
|
||||
return jumpConditional(f & ZF);
|
||||
case 2: // NC
|
||||
return jumpConditional(!(F() & CF));
|
||||
return jumpConditional(!(f & CF));
|
||||
case 3: // C
|
||||
return jumpConditional(F() & CF);
|
||||
return jumpConditional(f & CF);
|
||||
}
|
||||
throw std::logic_error("Unhandled JP conditional");
|
||||
}
|
||||
@ -100,30 +100,30 @@ void EightBit::LR35902::reti() {
|
||||
ei();
|
||||
}
|
||||
|
||||
bool EightBit::LR35902::returnConditionalFlag(int flag) {
|
||||
bool EightBit::LR35902::returnConditionalFlag(uint8_t& f, int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
return returnConditional(!(F() & ZF));
|
||||
return returnConditional(!(f & ZF));
|
||||
case 1: // Z
|
||||
return returnConditional(F() & ZF);
|
||||
return returnConditional(f & ZF);
|
||||
case 2: // NC
|
||||
return returnConditional(!(F() & CF));
|
||||
return returnConditional(!(f & CF));
|
||||
case 3: // C
|
||||
return returnConditional(F() & CF);
|
||||
return returnConditional(f & CF);
|
||||
}
|
||||
throw std::logic_error("Unhandled RET conditional");
|
||||
}
|
||||
|
||||
bool EightBit::LR35902::callConditionalFlag(int flag) {
|
||||
bool EightBit::LR35902::callConditionalFlag(uint8_t& f, int flag) {
|
||||
switch (flag) {
|
||||
case 0: // NZ
|
||||
return callConditional(!(F() & ZF));
|
||||
return callConditional(!(f & ZF));
|
||||
case 1: // Z
|
||||
return callConditional(F() & ZF);
|
||||
return callConditional(f & ZF);
|
||||
case 2: // NC
|
||||
return callConditional(!(F() & CF));
|
||||
return callConditional(!(f & CF));
|
||||
case 3: // C
|
||||
return callConditional(F() & CF);
|
||||
return callConditional(f & CF);
|
||||
}
|
||||
throw std::logic_error("Unhandled CALL conditional");
|
||||
}
|
||||
@ -132,35 +132,33 @@ bool EightBit::LR35902::callConditionalFlag(int flag) {
|
||||
|
||||
#pragma region 16-bit arithmetic
|
||||
|
||||
void EightBit::LR35902::sbc(register16_t& operand, register16_t value) {
|
||||
void EightBit::LR35902::sbc(uint8_t& f, register16_t& operand, register16_t value) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
auto result = before.word - value.word - (F() & CF);
|
||||
auto result = before.word - value.word - (f & CF);
|
||||
operand.word = result;
|
||||
|
||||
auto& f = F();
|
||||
clearFlag(f, ZF, operand.word);
|
||||
adjustHalfCarrySub(f, before.high, value.high, operand.high);
|
||||
setFlag(f, NF);
|
||||
setFlag(f, CF, result & Bit16);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::adc(register16_t& operand, register16_t value) {
|
||||
void EightBit::LR35902::adc(uint8_t& f, register16_t& operand, register16_t value) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
auto result = before.word + value.word + (F() & CF);
|
||||
auto result = before.word + value.word + (f & CF);
|
||||
operand.word = result;
|
||||
|
||||
auto& f = F();
|
||||
clearFlag(f, ZF, result);
|
||||
adjustHalfCarryAdd(f, before.high, value.high, operand.high);
|
||||
clearFlag(f, NF);
|
||||
setFlag(f, CF, result & Bit16);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::add(register16_t& operand, register16_t value) {
|
||||
void EightBit::LR35902::add(uint8_t& f, register16_t& operand, register16_t value) {
|
||||
|
||||
auto before = operand;
|
||||
|
||||
@ -168,7 +166,6 @@ void EightBit::LR35902::add(register16_t& operand, register16_t value) {
|
||||
|
||||
operand.word = result;
|
||||
|
||||
auto& f = F();
|
||||
clearFlag(f, NF);
|
||||
setFlag(f, CF, result & Bit16);
|
||||
adjustHalfCarryAdd(f, before.high, value.high, operand.high);
|
||||
@ -178,9 +175,7 @@ void EightBit::LR35902::add(register16_t& operand, register16_t value) {
|
||||
|
||||
#pragma region ALU
|
||||
|
||||
void EightBit::LR35902::add(uint8_t& operand, uint8_t value, int carry) {
|
||||
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::add(uint8_t& f, uint8_t& operand, uint8_t value, int carry) {
|
||||
|
||||
register16_t result;
|
||||
result.word = operand + value + carry;
|
||||
@ -194,13 +189,11 @@ void EightBit::LR35902::add(uint8_t& operand, uint8_t value, int carry) {
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::adc(uint8_t& operand, uint8_t value) {
|
||||
add(operand, value, F() & CF);
|
||||
void EightBit::LR35902::adc(uint8_t& f, uint8_t& operand, uint8_t value) {
|
||||
add(operand, value, f & CF);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::sub(uint8_t& operand, uint8_t value, int carry) {
|
||||
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::subtract(uint8_t& f, uint8_t& operand, uint8_t value, int carry) {
|
||||
|
||||
register16_t result;
|
||||
result.word = operand - value - carry;
|
||||
@ -214,112 +207,87 @@ void EightBit::LR35902::sub(uint8_t& operand, uint8_t value, int carry) {
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::sbc(uint8_t& operand, uint8_t value) {
|
||||
sub(operand, value, F() & CF);
|
||||
void EightBit::LR35902::sbc(uint8_t& f, uint8_t& operand, uint8_t value) {
|
||||
subtract(operand, value, f & CF);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::andr(uint8_t& operand, uint8_t value) {
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::andr(uint8_t& f, uint8_t& operand, uint8_t value) {
|
||||
operand &= value;
|
||||
setFlag(f, HC);
|
||||
clearFlag(f, CF | NF);
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::xorr(uint8_t& operand, uint8_t value) {
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::xorr(uint8_t& f, uint8_t& operand, uint8_t value) {
|
||||
operand ^= value;
|
||||
clearFlag(f, HC | CF | NF);
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::orr(uint8_t& operand, uint8_t value) {
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::orr(uint8_t& f, uint8_t& operand, uint8_t value) {
|
||||
operand |= value;
|
||||
clearFlag(f, HC | CF | NF);
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::compare(uint8_t value) {
|
||||
auto check = A();
|
||||
sub(check, value);
|
||||
void EightBit::LR35902::compare(uint8_t& f, uint8_t check, uint8_t value) {
|
||||
subtract(f, check, value);
|
||||
}
|
||||
|
||||
#pragma endregion ALU
|
||||
|
||||
#pragma region Shift and rotate
|
||||
|
||||
void EightBit::LR35902::rlc(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
auto carry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
setFlag(f, CF, carry);
|
||||
carry ? operand |= Bit0 : operand &= ~Bit0;
|
||||
void EightBit::LR35902::rlc(uint8_t& f, uint8_t& operand) {
|
||||
clearFlag(f, NF | HC);
|
||||
setFlag(f, CF, operand & Bit7);
|
||||
operand = _rotl8(operand, 1);
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::rrc(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
auto carry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
carry ? operand |= Bit7 : operand &= ~Bit7;
|
||||
setFlag(f, CF, carry);
|
||||
void EightBit::LR35902::rrc(uint8_t& f, uint8_t& operand) {
|
||||
clearFlag(f, NF | HC);
|
||||
setFlag(f, CF, operand & Bit0);
|
||||
operand = _rotr8(operand, 1);
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::rl(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
auto oldCarry = f & CF;
|
||||
auto newCarry = operand & Bit7;
|
||||
operand <<= 1;
|
||||
oldCarry ? operand |= Bit0 : operand &= ~Bit0;
|
||||
setFlag(f, CF, newCarry);
|
||||
void EightBit::LR35902::rl(uint8_t& f, uint8_t& operand) {
|
||||
clearFlag(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
setFlag(f, CF, operand & Bit7);
|
||||
operand = (operand << 1) | carry;
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::rr(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
auto oldCarry = f & CF;
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
operand |= oldCarry << 7;
|
||||
setFlag(f, CF, newCarry);
|
||||
void EightBit::LR35902::rr(uint8_t& f, uint8_t& operand) {
|
||||
clearFlag(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
setFlag(f, CF, operand & Bit0);
|
||||
operand = (operand >> 1) | (carry << 7);
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void EightBit::LR35902::sla(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
auto newCarry = operand & Bit7;
|
||||
void EightBit::LR35902::sla(uint8_t& f, uint8_t& operand) {
|
||||
clearFlag(f, NF | HC);
|
||||
setFlag(f, CF, operand & Bit7);
|
||||
operand <<= 1;
|
||||
setFlag(f, CF, newCarry);
|
||||
clearFlag(f, NF | HC);
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::sra(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
auto new7 = operand & Bit7;
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
operand |= new7;
|
||||
setFlag(f, CF, newCarry);
|
||||
void EightBit::LR35902::sra(uint8_t& f, uint8_t& operand) {
|
||||
clearFlag(f, NF | HC);
|
||||
setFlag(f, CF, operand & Bit0);
|
||||
operand = (operand >> 1) | operand & Bit7;
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::srl(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
auto newCarry = operand & Bit0;
|
||||
operand >>= 1;
|
||||
operand &= ~Bit7; // clear bit 7
|
||||
setFlag(f, CF, newCarry);
|
||||
void EightBit::LR35902::srl(uint8_t& f, uint8_t& operand) {
|
||||
clearFlag(f, NF | HC);
|
||||
setFlag(f, CF, operand & Bit0);
|
||||
operand = (operand >> 1) & ~Bit7;
|
||||
adjustZero<LR35902>(f, operand);
|
||||
}
|
||||
|
||||
@ -327,11 +295,10 @@ void EightBit::LR35902::srl(uint8_t& operand) {
|
||||
|
||||
#pragma region BIT/SET/RES
|
||||
|
||||
void EightBit::LR35902::bit(int n, uint8_t& operand) {
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::bit(uint8_t& f, int n, uint8_t& operand) {
|
||||
auto carry = f & CF;
|
||||
uint8_t discarded = operand;
|
||||
andr(discarded, 1 << n);
|
||||
andr(f, discarded, 1 << n);
|
||||
setFlag(f, CF, carry);
|
||||
}
|
||||
|
||||
@ -349,55 +316,48 @@ void EightBit::LR35902::set(int n, uint8_t& operand) {
|
||||
|
||||
#pragma region Miscellaneous instructions
|
||||
|
||||
void EightBit::LR35902::daa() {
|
||||
void EightBit::LR35902::daa(uint8_t& a, uint8_t& f) {
|
||||
|
||||
auto& f = F();
|
||||
auto updated = a;
|
||||
|
||||
uint8_t a = A();
|
||||
auto lowAdjust = (f & HC) | (lowNibble(a) > 9);
|
||||
auto highAdjust = (f & CF) | (a > 0x99);
|
||||
|
||||
auto lowAdjust = (f & HC) | ((A() & Mask4) > 9);
|
||||
auto highAdjust = (f & CF) | (A() > 0x99);
|
||||
|
||||
if (F() & NF) {
|
||||
if (f & NF) {
|
||||
if (lowAdjust)
|
||||
a -= 6;
|
||||
updated -= 6;
|
||||
if (highAdjust)
|
||||
a -= 0x60;
|
||||
updated -= 0x60;
|
||||
} else {
|
||||
if (lowAdjust)
|
||||
a += 6;
|
||||
updated += 6;
|
||||
if (highAdjust)
|
||||
a += 0x60;
|
||||
updated += 0x60;
|
||||
}
|
||||
|
||||
f = (f & (CF | NF)) | (A() > 0x99) | ((A() ^ a) & HC);
|
||||
f = (f & (CF | NF)) | (a > 0x99) | ((a ^ updated) & HC);
|
||||
a = updated;
|
||||
|
||||
adjustZero<LR35902>(f, a);
|
||||
|
||||
A() = a;
|
||||
}
|
||||
|
||||
void EightBit::LR35902::cpl() {
|
||||
A() = ~A();
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::cpl(uint8_t& a, uint8_t& f) {
|
||||
a = ~a;
|
||||
setFlag(f, HC | NF);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::scf() {
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::scf(uint8_t& a, uint8_t& f) {
|
||||
setFlag(f, CF);
|
||||
clearFlag(f, HC | NF);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::ccf() {
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::ccf(uint8_t& a, uint8_t& f) {
|
||||
auto carry = f & CF;
|
||||
clearFlag(f, CF, carry);
|
||||
clearFlag(f, NF | HC);
|
||||
}
|
||||
|
||||
void EightBit::LR35902::swap(uint8_t& operand) {
|
||||
auto& f = F();
|
||||
void EightBit::LR35902::swap(uint8_t& f, uint8_t& operand) {
|
||||
auto low = lowNibble(operand);
|
||||
auto high = highNibble(operand);
|
||||
operand = promoteNibble(low) | demoteNibble(high);
|
||||
@ -435,35 +395,37 @@ int EightBit::LR35902::execute(uint8_t opcode) {
|
||||
}
|
||||
|
||||
void EightBit::LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
auto& a = A();
|
||||
auto& f = F();
|
||||
switch (x) {
|
||||
case 0: // rot[y] r[z]
|
||||
switch (y) {
|
||||
case 0:
|
||||
rlc(R(z));
|
||||
rlc(f, R(z, a));
|
||||
break;
|
||||
case 1:
|
||||
rrc(R(z));
|
||||
rrc(f, R(z, a));
|
||||
break;
|
||||
case 2:
|
||||
rl(R(z));
|
||||
rl(f, R(z, a));
|
||||
break;
|
||||
case 3:
|
||||
rr(R(z));
|
||||
rr(f, R(z, a));
|
||||
break;
|
||||
case 4:
|
||||
sla(R(z));
|
||||
sla(f, R(z, a));
|
||||
break;
|
||||
case 5:
|
||||
sra(R(z));
|
||||
sra(f, R(z, a));
|
||||
break;
|
||||
case 6:
|
||||
swap(R(z));
|
||||
swap(f, R(z, a));
|
||||
break;
|
||||
case 7:
|
||||
srl(R(z));
|
||||
srl(f, R(z, a));
|
||||
break;
|
||||
}
|
||||
adjustZero<LR35902>(F(), R(z));
|
||||
adjustZero<LR35902>(f, R(z, a));
|
||||
cycles += 2;
|
||||
if (z == 6) {
|
||||
m_bus.fireWriteBusEvent();
|
||||
@ -471,7 +433,7 @@ void EightBit::LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
break;
|
||||
case 1: // BIT y, r[z]
|
||||
bit(y, R(z));
|
||||
bit(f, y, R(z, a));
|
||||
cycles += 2;
|
||||
if (z == 6) {
|
||||
m_bus.fireReadBusEvent();
|
||||
@ -479,7 +441,7 @@ void EightBit::LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
break;
|
||||
case 2: // RES y, r[z]
|
||||
res(y, R(z));
|
||||
res(y, R(z, a));
|
||||
cycles += 2;
|
||||
if (z == 6) {
|
||||
m_bus.fireWriteBusEvent();
|
||||
@ -487,7 +449,7 @@ void EightBit::LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
break;
|
||||
case 3: // SET y, r[z]
|
||||
set(y, R(z));
|
||||
set(y, R(z, a));
|
||||
cycles += 2;
|
||||
if (z == 6) {
|
||||
m_bus.fireWriteBusEvent();
|
||||
@ -498,6 +460,8 @@ void EightBit::LR35902::executeCB(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
|
||||
void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
auto& a = A();
|
||||
auto& f = F();
|
||||
switch (x) {
|
||||
case 0:
|
||||
switch (z) {
|
||||
@ -519,14 +483,13 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
jr(fetchByte());
|
||||
cycles += 4;
|
||||
break;
|
||||
default: { // JR cc,d
|
||||
auto condition = y - 4;
|
||||
if (condition < 4) {
|
||||
if (jrConditionalFlag(condition))
|
||||
cycles++;
|
||||
cycles += 2;
|
||||
}
|
||||
}
|
||||
case 4: // JR cc,d
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
if (jrConditionalFlag(f, y - 4))
|
||||
cycles++;
|
||||
cycles += 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -537,7 +500,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
cycles += 3;
|
||||
break;
|
||||
case 1: // ADD HL,rp
|
||||
add(HL(), RP(p));
|
||||
add(f, HL(), RP(p));
|
||||
cycles += 2;
|
||||
break;
|
||||
}
|
||||
@ -547,19 +510,19 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
case 0:
|
||||
switch (p) {
|
||||
case 0: // LD (BC),A
|
||||
m_memory.write(BC().word, A());
|
||||
m_memory.write(BC().word, a);
|
||||
cycles += 2;
|
||||
break;
|
||||
case 1: // LD (DE),A
|
||||
m_memory.write(DE().word, A());
|
||||
m_memory.write(DE().word, a);
|
||||
cycles += 2;
|
||||
break;
|
||||
case 2: // GB: LDI (HL),A
|
||||
m_memory.write(HL().word++, A());
|
||||
m_memory.write(HL().word++, a);
|
||||
cycles += 2;
|
||||
break;
|
||||
case 3: // GB: LDD (HL),A
|
||||
m_memory.write(HL().word--, A());
|
||||
m_memory.write(HL().word--, a);
|
||||
cycles += 2;
|
||||
break;
|
||||
}
|
||||
@ -567,19 +530,19 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
case 1:
|
||||
switch (p) {
|
||||
case 0: // LD A,(BC)
|
||||
A() = m_memory.read(BC().word);
|
||||
a = m_memory.read(BC().word);
|
||||
cycles += 2;
|
||||
break;
|
||||
case 1: // LD A,(DE)
|
||||
A() = m_memory.read(DE().word);
|
||||
a = m_memory.read(DE().word);
|
||||
cycles += 2;
|
||||
break;
|
||||
case 2: // GB: LDI A,(HL)
|
||||
A() = m_memory.read(HL().word++);
|
||||
a = m_memory.read(HL().word++);
|
||||
cycles += 2;
|
||||
break;
|
||||
case 3: // GB: LDD A,(HL)
|
||||
A() = m_memory.read(HL().word--);
|
||||
a = m_memory.read(HL().word--);
|
||||
cycles += 2;
|
||||
break;
|
||||
}
|
||||
@ -598,7 +561,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
cycles += 2;
|
||||
break;
|
||||
case 4: // 8-bit INC
|
||||
postIncrement(F(), ++R(y)); // INC r
|
||||
postIncrement(f, ++R(y, a)); // INC r
|
||||
cycles++;
|
||||
if (y == 6) {
|
||||
m_bus.fireWriteBusEvent();
|
||||
@ -606,7 +569,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
break;
|
||||
case 5: // 8-bit DEC
|
||||
postDecrement(F(), --R(y)); // DEC r
|
||||
postDecrement(f, --R(y, a)); // DEC r
|
||||
cycles++;
|
||||
if (y == 6) {
|
||||
m_bus.fireWriteBusEvent();
|
||||
@ -614,7 +577,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
break;
|
||||
case 6: // 8-bit load immediate
|
||||
R(y) = fetchByte();
|
||||
R(y, a) = fetchByte();
|
||||
if (y == 6)
|
||||
m_bus.fireWriteBusEvent();
|
||||
cycles += 2;
|
||||
@ -622,32 +585,28 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
case 7: // Assorted operations on accumulator/flags
|
||||
switch (y) {
|
||||
case 0:
|
||||
rlc(A());
|
||||
clearFlag(F(), ZF);
|
||||
rlc(f, a);
|
||||
break;
|
||||
case 1:
|
||||
rrc(A());
|
||||
clearFlag(F(), ZF);
|
||||
rrc(f, a);
|
||||
break;
|
||||
case 2:
|
||||
rl(A());
|
||||
clearFlag(F(), ZF);
|
||||
rl(f, a);
|
||||
break;
|
||||
case 3:
|
||||
rr(A());
|
||||
clearFlag(F(), ZF);
|
||||
rr(f, a);
|
||||
break;
|
||||
case 4:
|
||||
daa();
|
||||
daa(a, f);
|
||||
break;
|
||||
case 5:
|
||||
cpl();
|
||||
cpl(a, f);
|
||||
break;
|
||||
case 6:
|
||||
scf();
|
||||
scf(a, f);
|
||||
break;
|
||||
case 7:
|
||||
ccf();
|
||||
ccf(a, f);
|
||||
break;
|
||||
}
|
||||
cycles++;
|
||||
@ -658,7 +617,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
if (z == 6 && y == 6) { // Exception (replaces LD (HL), (HL))
|
||||
halt();
|
||||
} else {
|
||||
R(y) = R(z);
|
||||
R(y, a) = R(z, a);
|
||||
if ((y == 6) || (z == 6)) { // M operations
|
||||
if (y == 6)
|
||||
m_bus.fireWriteBusEvent();
|
||||
@ -672,28 +631,28 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
case 2: // Operate on accumulator and register/memory location
|
||||
switch (y) {
|
||||
case 0: // ADD A,r
|
||||
add(A(), R(z));
|
||||
add(f, a, R(z, a));
|
||||
break;
|
||||
case 1: // ADC A,r
|
||||
adc(A(), R(z));
|
||||
adc(f, a, R(z, a));
|
||||
break;
|
||||
case 2: // SUB r
|
||||
sub(A(), R(z));
|
||||
subtract(f, a, R(z, a));
|
||||
break;
|
||||
case 3: // SBC A,r
|
||||
sbc(A(), R(z));
|
||||
sbc(f, a, R(z, a));
|
||||
break;
|
||||
case 4: // AND r
|
||||
andr(A(), R(z));
|
||||
andr(f, a, R(z, a));
|
||||
break;
|
||||
case 5: // XOR r
|
||||
xorr(A(), R(z));
|
||||
xorr(f, a, R(z, a));
|
||||
break;
|
||||
case 6: // OR r
|
||||
orr(A(), R(z));
|
||||
orr(f, a, R(z, a));
|
||||
break;
|
||||
case 7: // CP r
|
||||
compare(R(z));
|
||||
compare(f, a, R(z, a));
|
||||
break;
|
||||
}
|
||||
cycles++;
|
||||
@ -705,45 +664,45 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
case 3:
|
||||
switch (z) {
|
||||
case 0: // Conditional return
|
||||
if (y < 4) {
|
||||
if (returnConditionalFlag(y))
|
||||
switch (y) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
if (returnConditionalFlag(f, y))
|
||||
cycles += 3;
|
||||
cycles += 2;
|
||||
} else {
|
||||
switch (y) {
|
||||
case 4: // GB: LD (FF00 + n),A
|
||||
m_bus.writeRegister(fetchByte(), A());
|
||||
cycles += 3;
|
||||
break;
|
||||
case 5: { // GB: ADD SP,dd
|
||||
auto& f = F();
|
||||
auto before = SP();
|
||||
auto value = fetchByte();
|
||||
auto result = SP().word + (int8_t)value;
|
||||
SP().word = result;
|
||||
clearFlag(f, ZF | NF);
|
||||
setFlag(f, CF, result & Bit16);
|
||||
adjustHalfCarryAdd(f, before.high, value, SP().high);
|
||||
}
|
||||
cycles += 4;
|
||||
break;
|
||||
case 6: // GB: LD A,(FF00 + n)
|
||||
A() = m_bus.readRegister(fetchByte());
|
||||
cycles += 3;
|
||||
break;
|
||||
case 7: { // GB: LD HL,SP + dd
|
||||
auto& f = F();
|
||||
auto before = HL();
|
||||
auto value = fetchByte();
|
||||
auto result = SP().word + (int8_t)value;
|
||||
HL().word = result;
|
||||
clearFlag(f, ZF | NF);
|
||||
setFlag(f, CF, result & Bit16);
|
||||
adjustHalfCarryAdd(f, before.high, value, HL().high);
|
||||
}
|
||||
cycles += 3;
|
||||
break;
|
||||
break;
|
||||
case 4: // GB: LD (FF00 + n),A
|
||||
m_bus.writeRegister(fetchByte(), a);
|
||||
cycles += 3;
|
||||
break;
|
||||
case 5: { // GB: ADD SP,dd
|
||||
auto before = SP();
|
||||
auto value = fetchByte();
|
||||
auto result = SP().word + (int8_t)value;
|
||||
SP().word = result;
|
||||
clearFlag(f, ZF | NF);
|
||||
setFlag(f, CF, result & Bit16);
|
||||
adjustHalfCarryAdd(f, before.high, value, SP().high);
|
||||
}
|
||||
cycles += 4;
|
||||
break;
|
||||
case 6: // GB: LD A,(FF00 + n)
|
||||
a = m_bus.readRegister(fetchByte());
|
||||
cycles += 3;
|
||||
break;
|
||||
case 7: { // GB: LD HL,SP + dd
|
||||
auto before = HL();
|
||||
auto value = fetchByte();
|
||||
auto result = SP().word + (int8_t)value;
|
||||
HL().word = result;
|
||||
clearFlag(f, ZF | NF);
|
||||
setFlag(f, CF, result & Bit16);
|
||||
adjustHalfCarryAdd(f, before.high, value, HL().high);
|
||||
}
|
||||
cycles += 3;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1: // POP & various ops
|
||||
@ -774,30 +733,32 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
break;
|
||||
case 2: // Conditional jump
|
||||
if (y < 4) {
|
||||
jumpConditionalFlag(y);
|
||||
switch (y) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
jumpConditionalFlag(f, y);
|
||||
cycles += 3;
|
||||
} else {
|
||||
switch (y) {
|
||||
case 4: // GB: LD (FF00 + C),A
|
||||
m_bus.writeRegister(C(), A());
|
||||
cycles += 2;
|
||||
break;
|
||||
case 5: // GB: LD (nn),A
|
||||
fetchWord();
|
||||
m_bus.write(MEMPTR().word, A());
|
||||
cycles += 4;
|
||||
break;
|
||||
case 6: // GB: LD A,(FF00 + C)
|
||||
A() = m_bus.readRegister(C());
|
||||
cycles += 2;
|
||||
break;
|
||||
case 7: // GB: LD A,(nn)
|
||||
fetchWord();
|
||||
A() = m_bus.read(MEMPTR().word);
|
||||
cycles += 4;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4: // GB: LD (FF00 + C),A
|
||||
m_bus.writeRegister(C(), a);
|
||||
cycles += 2;
|
||||
break;
|
||||
case 5: // GB: LD (nn),A
|
||||
fetchWord();
|
||||
m_bus.write(MEMPTR().word, a);
|
||||
cycles += 4;
|
||||
break;
|
||||
case 6: // GB: LD A,(FF00 + C)
|
||||
a = m_bus.readRegister(C());
|
||||
cycles += 2;
|
||||
break;
|
||||
case 7: // GB: LD A,(nn)
|
||||
fetchWord();
|
||||
a = m_bus.read(MEMPTR().word);
|
||||
cycles += 4;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: // Assorted operations
|
||||
@ -822,7 +783,7 @@ void EightBit::LR35902::executeOther(int x, int y, int z, int p, int q) {
|
||||
}
|
||||
break;
|
||||
case 4: // Conditional call: CALL cc[y], nn
|
||||
if (callConditionalFlag(y))
|
||||
if (callConditionalFlag(f, y))
|
||||
cycles += 3;
|
||||
cycles += 3;
|
||||
break;
|
||||
@ -845,28 +806,28 @@ void EightBit::LR35902::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(), fetchByte());
|
||||
add(f, a, fetchByte());
|
||||
break;
|
||||
case 1: // ADC A,n
|
||||
adc(A(), fetchByte());
|
||||
adc(f, a, fetchByte());
|
||||
break;
|
||||
case 2: // SUB n
|
||||
sub(A(), fetchByte());
|
||||
subtract(f, a, fetchByte());
|
||||
break;
|
||||
case 3: // SBC A,n
|
||||
sbc(A(), fetchByte());
|
||||
sbc(f, a, fetchByte());
|
||||
break;
|
||||
case 4: // AND n
|
||||
andr(A(), fetchByte());
|
||||
andr(f, a, fetchByte());
|
||||
break;
|
||||
case 5: // XOR n
|
||||
xorr(A(), fetchByte());
|
||||
xorr(f, a, fetchByte());
|
||||
break;
|
||||
case 6: // OR n
|
||||
orr(A(), fetchByte());
|
||||
orr(f, a, fetchByte());
|
||||
break;
|
||||
case 7: // CP n
|
||||
compare(fetchByte());
|
||||
compare(f, a, fetchByte());
|
||||
break;
|
||||
}
|
||||
cycles += 2;
|
||||
|
@ -322,7 +322,7 @@ namespace EightBit {
|
||||
|
||||
static uint8_t& bit(uint8_t& f, int n, uint8_t& operand);
|
||||
static uint8_t& res(int n, uint8_t& operand);
|
||||
static uint8_t& set(int nit, uint8_t& operand);
|
||||
static uint8_t& set(int n, uint8_t& operand);
|
||||
|
||||
static void daa(uint8_t& a, uint8_t& f);
|
||||
|
||||
|
@ -140,14 +140,6 @@ bool EightBit::Z80::jrConditionalFlag(uint8_t& f, int flag) {
|
||||
return jrConditional(!(f & CF));
|
||||
case 3: // C
|
||||
return jrConditional(f & CF);
|
||||
case 4: // PO
|
||||
return jrConditional(!(f & PF));
|
||||
case 5: // PE
|
||||
return jrConditional(f & PF);
|
||||
case 6: // P
|
||||
return jrConditional(!(f & SF));
|
||||
case 7: // M
|
||||
return jrConditional(f & SF);
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
@ -1149,11 +1141,16 @@ void EightBit::Z80::executeOther(int x, int y, int z, int p, int q) {
|
||||
jr(fetchByte());
|
||||
cycles += 12;
|
||||
break;
|
||||
default: // JR cc,d
|
||||
case 4: // JR cc,d
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
if (jrConditionalFlag(f, y - 4))
|
||||
cycles += 5;
|
||||
cycles += 5;
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
break;
|
||||
case 1: // 16-bit load immediate/add
|
||||
|
Loading…
Reference in New Issue
Block a user