diff --git a/src/cpu.cpp b/src/cpu.cpp index f87943f..90f2b2d 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -208,6 +208,22 @@ void CPU::update() case 0x8d: adc8(); break; case 0x8e: adc8(); break; case 0x8f: adc8(); break; + case 0x90: sub8(); break; + case 0x91: sub8(); break; + case 0x92: sub8(); break; + case 0x93: sub8(); break; + case 0x94: sub8(); break; + case 0x95: sub8(); break; + case 0x96: sub8(); break; + case 0x97: sub8(); break; + case 0x98: sbc8(); break; + case 0x99: sbc8(); break; + case 0x9a: sbc8(); break; + case 0x9b: sbc8(); break; + case 0x9c: sbc8(); break; + case 0x9d: sbc8(); break; + case 0x9e: sbc8(); break; + case 0x9f: sbc8(); break; case 0xa0: and8(); break; case 0xa1: and8(); break; case 0xa2: and8(); break; @@ -240,8 +256,10 @@ void CPU::update() case 0xd1: pop(); break; case 0xd4: call(); break; case 0xd5: push(); break; + case 0xd6: sub8(); break; case 0xd7: rst(); break; case 0xdc: call(); break; + case 0xde: sbc8(); break; case 0xdf: rst(); break; case 0xe0: ldffi8(); break; case 0xe1: pop(); break; @@ -420,6 +438,54 @@ void CPU::and8() } } +void CPU::cp() +{ + auto compare = [this](uint32_t register_) -> void { + // CP A,r8, flags: Z 1 H C + m_wait_cycles += 4; + + // Subtract the value in r8 from A and set flags accordingly, + // but don't store the result + + // Set flags + // Zero flag + m_zf = ((m_a - register_) & 0xff) == 0; + m_nf = 1; + // Note: for negation between two positive numbers the carry result is flipped! + m_hf = !isCarry(m_a, register_, 0x10); + m_cf = !isCarry(m_a, register_, 0x100); + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0xb8: /* CP A,B */ compare(m_b); break; + case 0xb9: /* CP A,C */ compare(m_c); break; + case 0xba: /* CP A,D */ compare(m_d); break; + case 0xbb: /* CP A,E */ compare(m_e); break; + case 0xbc: /* CP A,H */ compare(m_h); break; + case 0xbd: /* CP A,L */ compare(m_l); break; + case 0xbe: /* CP A,(HL) */ { + m_wait_cycles += 4; // + 4 = 8 total + + // Subtract the byte pointed to by HL from A and set flags accordingly, + // but don't store the result + compare(read(hl())); + break; + } + case 0xbf: /* CP A,A */ compare(m_a); break; + case 0xfe: /* CP A,i8 */ { + m_wait_cycles += 4; // + 4 = 8 total + + // Subtract the value i8 from A and set flags accordingly, + // but don't store the result + compare(pcRead()); + break; + } + default: + VERIFY_NOT_REACHED(); + } +} + void CPU::dec8() { auto decrement = [this](uint32_t& register_) -> void { @@ -500,6 +566,102 @@ void CPU::inc8() } } +void CPU::sbc8() +{ + auto subtract_carry = [this](uint32_t register_) -> void { + // SBC A,r8, flags: Z 1 H C + m_wait_cycles += 4; + + uint32_t old_carry = m_cf; + + // Set flags + m_nf = 1; + // Note: for negation between two positive numbers the carry result is flipped! + m_hf = !isCarry(m_a, register_, 0x10); + m_cf = !isCarry(m_a, (register_ + (old_carry) ? 1 : 0), 0x100); + + // Subtract the value in r8 and the carry flag from A + m_a = (m_a - register_ - (old_carry) ? 1 : 0) & 0xff; + + // Zero flag + m_zf = m_a == 0; + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0x98: /* SBC A,B */ subtract_carry(m_b); break; + case 0x99: /* SBC A,C */ subtract_carry(m_c); break; + case 0x9a: /* SBC A,D */ subtract_carry(m_d); break; + case 0x9b: /* SBC A,E */ subtract_carry(m_e); break; + case 0x9c: /* SBC A,H */ subtract_carry(m_h); break; + case 0x9d: /* SBC A,L */ subtract_carry(m_l); break; + case 0x9e: /* SBC A,(HL) */ { + m_wait_cycles += 4; // + 4 = 8 total + + // Subtract the byte pointed to by HL and the carry flag from A + subtract_carry(read(hl())); + break; + } + case 0x9f: /* SBC A,A */ subtract_carry(m_a); break; + case 0xde: /* SBC A,i8 */ { + m_wait_cycles += 4; // + 4 = 8 total + + // Subtract the value i8 and the carry flag from A + subtract_carry(pcRead()); + break; + } + default: + VERIFY_NOT_REACHED(); + } +} + +void CPU::sub8() +{ + auto subtract = [this](uint32_t register_) -> void { + // SUB A,r8, flags: Z 1 H C + m_wait_cycles += 4; + + // Set flags + m_nf = 1; + // Note: for negation between two positive numbers the carry result is flipped! + m_hf = !isCarry(m_a, register_, 0x10); + m_cf = !isCarry(m_a, register_, 0x100); + + // Subtract the value in r8 from A + m_a = (m_a - register_) & 0xff; + + // Zero flag + m_zf = m_a == 0; + }; + + uint8_t opcode = pcRead(); + switch (opcode) { + case 0x90: /* SUB A,B */ subtract(m_b); break; + case 0x91: /* SUB A,C */ subtract(m_c); break; + case 0x92: /* SUB A,D */ subtract(m_d); break; + case 0x93: /* SUB A,E */ subtract(m_e); break; + case 0x94: /* SUB A,H */ subtract(m_h); break; + case 0x95: /* SUB A,L */ subtract(m_l); break; + case 0x96: /* SUB A,(HL) */ { + m_wait_cycles += 4; // + 4 = 8 total + + // Subtract the byte pointed to by HL from A + subtract(read(hl())); + break; + } + case 0x97: /* SUB A,A */ subtract(m_a); break; + case 0xd6: /* SUB A,i8 */ { + m_wait_cycles += 4; // + 4 = 8 total + + // Subtract the value i8 from A + subtract(pcRead()); + break; + } + default: + VERIFY_NOT_REACHED(); + } +} + void CPU::xor8() { uint8_t opcode = pcRead(); @@ -935,45 +1097,6 @@ void CPU::ra() m_hf = 0; } -void CPU::cp() -{ - uint8_t opcode = pcRead(); - uint8_t value = 0; - switch (opcode) { - case 0xb8: /* CP B */ value = m_b; break; - case 0xb9: /* CP C */ value = m_c; break; - case 0xba: /* CP D */ value = m_d; break; - case 0xbb: /* CP E */ value = m_e; break; - case 0xbc: /* CP H */ value = m_h; break; - case 0xbd: /* CP L */ value = m_l; break; - case 0xbe: // CP,(HL) - m_wait_cycles += 4; - value = read(hl()); - break; - case 0xbf: // CP A, flags: 1 1 0 0 - m_wait_cycles += 4; - // A - A - m_zf = m_nf = 1; - m_hf = m_cf = 0; - return; // Early return as we already set the flags - case 0xfe: // CP i8 - m_wait_cycles += 4; - value = pcRead(); - break; - default: - VERIFY_NOT_REACHED(); - } - - // CP r8, flags: Z 1 H C - m_wait_cycles += 4; - - // Set flags - m_zf = ((m_a - value) & 0xff) == 0; - m_nf = 1; - m_hf = isCarry(m_a, value, 0x10); - m_cf = isCarry(m_a, value, 0x100); -} - void CPU::ldffi8() { uint8_t opcode = pcRead(); diff --git a/src/cpu.h b/src/cpu.h index 4cf9024..c8d7d6a 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -31,8 +31,11 @@ public: void adc8(); void add8(); void and8(); + void cp(); void dec8(); void inc8(); + void sbc8(); + void sub8(); void xor8(); // 16-bit @@ -65,7 +68,6 @@ public: // Load Instructions // 8-bit - void cp(); void lda8(); void ldffi8(); void ldi8();