|
|
@ -69,31 +69,39 @@ void CPU::update() |
|
|
|
|
|
|
|
|
|
|
|
case 0x01: ldi16(); break; |
|
|
|
case 0x01: ldi16(); break; |
|
|
|
case 0x02: ldr8(); break; |
|
|
|
case 0x02: ldr8(); break; |
|
|
|
|
|
|
|
case 0x04: inc(); break; |
|
|
|
case 0x06: ldi8(); break; |
|
|
|
case 0x06: ldi8(); break; |
|
|
|
case 0x08: ldr16(); break; |
|
|
|
case 0x08: ldr16(); break; |
|
|
|
case 0x0a: ldr8(); break; |
|
|
|
case 0x0a: ldr8(); break; |
|
|
|
case 0x0b: decr16(); break; |
|
|
|
case 0x0b: decr16(); break; |
|
|
|
|
|
|
|
case 0x0c: inc(); break; |
|
|
|
case 0x0d: dec8(); break; |
|
|
|
case 0x0d: dec8(); break; |
|
|
|
case 0x0e: ldi8(); break; |
|
|
|
case 0x0e: ldi8(); break; |
|
|
|
case 0x11: ldi16(); break; |
|
|
|
case 0x11: ldi16(); break; |
|
|
|
case 0x12: ldr8(); break; |
|
|
|
case 0x12: ldr8(); break; |
|
|
|
|
|
|
|
case 0x14: inc(); break; |
|
|
|
case 0x16: ldi8(); break; |
|
|
|
case 0x16: ldi8(); break; |
|
|
|
case 0x1a: ldr8(); break; |
|
|
|
case 0x1a: ldr8(); break; |
|
|
|
case 0x1b: decr16(); break; |
|
|
|
case 0x1b: decr16(); break; |
|
|
|
|
|
|
|
case 0x1c: inc(); break; |
|
|
|
case 0x1e: ldi8(); break; |
|
|
|
case 0x1e: ldi8(); break; |
|
|
|
case 0x20: jr8(); break; |
|
|
|
case 0x20: jr8(); break; |
|
|
|
case 0x21: ldi16(); break; |
|
|
|
case 0x21: ldi16(); break; |
|
|
|
case 0x22: ldr8(); break; |
|
|
|
case 0x22: ldr8(); break; |
|
|
|
|
|
|
|
case 0x24: inc(); break; |
|
|
|
case 0x26: ldi8(); break; |
|
|
|
case 0x26: ldi8(); break; |
|
|
|
case 0x2a: lda8(); break; |
|
|
|
case 0x2a: lda8(); break; |
|
|
|
case 0x2b: decr16(); break; |
|
|
|
case 0x2b: decr16(); break; |
|
|
|
|
|
|
|
case 0x2c: inc(); break; |
|
|
|
case 0x2e: ldi8(); break; |
|
|
|
case 0x2e: ldi8(); break; |
|
|
|
case 0x2f: misc(); break; |
|
|
|
case 0x2f: misc(); break; |
|
|
|
case 0x31: ldi16(); break; |
|
|
|
case 0x31: ldi16(); break; |
|
|
|
case 0x32: ldr8(); break; |
|
|
|
case 0x32: ldr8(); break; |
|
|
|
|
|
|
|
case 0x34: inc(); break; |
|
|
|
case 0x36: ldi8(); break; |
|
|
|
case 0x36: ldi8(); break; |
|
|
|
case 0x3a: ldr8(); break; |
|
|
|
case 0x3a: ldr8(); break; |
|
|
|
case 0x3b: decr16(); break; |
|
|
|
case 0x3b: decr16(); break; |
|
|
|
|
|
|
|
case 0x3c: inc(); break; |
|
|
|
case 0x3e: ldi8(); break; |
|
|
|
case 0x3e: ldi8(); break; |
|
|
|
case 0x40: ldr8(); break; |
|
|
|
case 0x40: ldr8(); break; |
|
|
|
case 0x41: ldr8(); break; |
|
|
|
case 0x41: ldr8(); break; |
|
|
@ -154,6 +162,14 @@ void CPU::update() |
|
|
|
case 0x7f: ldr8(); break; |
|
|
|
case 0x7f: ldr8(); break; |
|
|
|
case 0xa8: xor8(); break; |
|
|
|
case 0xa8: xor8(); break; |
|
|
|
case 0xaf: xor8(); break; |
|
|
|
case 0xaf: xor8(); break; |
|
|
|
|
|
|
|
case 0xb8: cp(); break; |
|
|
|
|
|
|
|
case 0xb9: cp(); break; |
|
|
|
|
|
|
|
case 0xba: cp(); break; |
|
|
|
|
|
|
|
case 0xbb: cp(); break; |
|
|
|
|
|
|
|
case 0xbc: cp(); break; |
|
|
|
|
|
|
|
case 0xbd: cp(); break; |
|
|
|
|
|
|
|
case 0xbe: cp(); break; |
|
|
|
|
|
|
|
case 0xbf: cp(); break; |
|
|
|
case 0xc3: jp16(); break; |
|
|
|
case 0xc3: jp16(); break; |
|
|
|
case 0xc6: add(); break; |
|
|
|
case 0xc6: add(); break; |
|
|
|
case 0xcd: call(); break; |
|
|
|
case 0xcd: call(); break; |
|
|
@ -165,6 +181,7 @@ void CPU::update() |
|
|
|
case 0xf8: ldr16(); break; |
|
|
|
case 0xf8: ldr16(); break; |
|
|
|
case 0xf9: ldr16(); break; |
|
|
|
case 0xf9: ldr16(); break; |
|
|
|
case 0xfa: lda8(); break; |
|
|
|
case 0xfa: lda8(); break; |
|
|
|
|
|
|
|
case 0xfe: cp(); break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
|
print("opcode {:#x} not implemented\n", opcode); |
|
|
|
print("opcode {:#x} not implemented\n", opcode); |
|
|
@ -481,6 +498,93 @@ void CPU::ldr8() |
|
|
|
m_wait_cycles += 4; |
|
|
|
m_wait_cycles += 4; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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::inc() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
auto increment = [this](uint32_t& reg) -> void { |
|
|
|
|
|
|
|
// INC r8, flags: Z 0 H -
|
|
|
|
|
|
|
|
m_wait_cycles += 4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set flags
|
|
|
|
|
|
|
|
m_nf = 0; |
|
|
|
|
|
|
|
m_hf = isCarry(reg, 1, 0x10); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Increment value in register r8 by 1
|
|
|
|
|
|
|
|
reg = (reg + 1) & 0xff; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Zero flag
|
|
|
|
|
|
|
|
m_zf = reg == 0; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t opcode = pcRead(); |
|
|
|
|
|
|
|
switch (opcode) { |
|
|
|
|
|
|
|
case 0x04: /* INC B */ increment(m_b); break; |
|
|
|
|
|
|
|
case 0x0c: /* INC C */ increment(m_c); break; |
|
|
|
|
|
|
|
case 0x14: /* INC D */ increment(m_d); break; |
|
|
|
|
|
|
|
case 0x1c: /* INC E */ increment(m_e); break; |
|
|
|
|
|
|
|
case 0x24: /* INC H */ increment(m_h); break; |
|
|
|
|
|
|
|
case 0x2c: /* INC L */ increment(m_l); break; |
|
|
|
|
|
|
|
case 0x34: { /* INC (HL) */ |
|
|
|
|
|
|
|
m_wait_cycles += 12; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t data = read(hl()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set flags
|
|
|
|
|
|
|
|
m_nf = 0; |
|
|
|
|
|
|
|
m_hf = isCarry(data, 1, 0x10); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Increment the byte pointed to by HL by 1
|
|
|
|
|
|
|
|
data = (data + 1) & 0xff; |
|
|
|
|
|
|
|
write(hl(), data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Zero flag
|
|
|
|
|
|
|
|
m_zf = data == 0; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case 0x3c: /* INC A */ increment(m_a); break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
VERIFY_NOT_REACHED(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CPU::ldffi8() |
|
|
|
void CPU::ldffi8() |
|
|
|
{ |
|
|
|
{ |
|
|
|
uint8_t opcode = pcRead(); |
|
|
|
uint8_t opcode = pcRead(); |
|
|
|