Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
baa679904c | ||
|
|
0c4d7b2112 | ||
|
|
3346b5329a |
+162
-12
@@ -233,7 +233,21 @@ void CPU::update()
|
|||||||
case 0xa6: and8(); break;
|
case 0xa6: and8(); break;
|
||||||
case 0xa7: and8(); break;
|
case 0xa7: and8(); break;
|
||||||
case 0xa8: xor8(); break;
|
case 0xa8: xor8(); break;
|
||||||
|
case 0xa9: xor8(); break;
|
||||||
|
case 0xaa: xor8(); break;
|
||||||
|
case 0xab: xor8(); break;
|
||||||
|
case 0xac: xor8(); break;
|
||||||
|
case 0xad: xor8(); break;
|
||||||
|
case 0xae: xor8(); break;
|
||||||
case 0xaf: xor8(); break;
|
case 0xaf: xor8(); break;
|
||||||
|
case 0xb0: or8(); break;
|
||||||
|
case 0xb1: or8(); break;
|
||||||
|
case 0xb2: or8(); break;
|
||||||
|
case 0xb3: or8(); break;
|
||||||
|
case 0xb4: or8(); break;
|
||||||
|
case 0xb5: or8(); break;
|
||||||
|
case 0xb6: or8(); break;
|
||||||
|
case 0xb7: or8(); break;
|
||||||
case 0xb8: cp(); break;
|
case 0xb8: cp(); break;
|
||||||
case 0xb9: cp(); break;
|
case 0xb9: cp(); break;
|
||||||
case 0xba: cp(); break;
|
case 0xba: cp(); break;
|
||||||
@@ -242,22 +256,31 @@ void CPU::update()
|
|||||||
case 0xbd: cp(); break;
|
case 0xbd: cp(); break;
|
||||||
case 0xbe: cp(); break;
|
case 0xbe: cp(); break;
|
||||||
case 0xbf: cp(); break;
|
case 0xbf: cp(); break;
|
||||||
|
case 0xc0: ret(); break;
|
||||||
case 0xc1: pop(); break;
|
case 0xc1: pop(); break;
|
||||||
|
case 0xc2: jp16(); break;
|
||||||
case 0xc3: jp16(); break;
|
case 0xc3: jp16(); break;
|
||||||
case 0xc4: call(); break;
|
case 0xc4: call(); break;
|
||||||
case 0xc5: push(); break;
|
case 0xc5: push(); break;
|
||||||
case 0xc6: add8(); break;
|
case 0xc6: add8(); break;
|
||||||
case 0xc7: rst(); break;
|
case 0xc7: rst(); break;
|
||||||
|
case 0xc8: ret(); break;
|
||||||
|
case 0xc9: ret(); break;
|
||||||
|
case 0xca: jp16(); break;
|
||||||
case 0xcb: prefix(); break;
|
case 0xcb: prefix(); break;
|
||||||
case 0xcc: call(); break;
|
case 0xcc: call(); break;
|
||||||
case 0xcd: call(); break;
|
case 0xcd: call(); break;
|
||||||
case 0xce: adc8(); break;
|
case 0xce: adc8(); break;
|
||||||
case 0xcf: rst(); break;
|
case 0xcf: rst(); break;
|
||||||
|
case 0xd0: ret(); break;
|
||||||
case 0xd1: pop(); break;
|
case 0xd1: pop(); break;
|
||||||
|
case 0xd2: jp16(); break;
|
||||||
case 0xd4: call(); break;
|
case 0xd4: call(); break;
|
||||||
case 0xd5: push(); break;
|
case 0xd5: push(); break;
|
||||||
case 0xd6: sub8(); break;
|
case 0xd6: sub8(); break;
|
||||||
case 0xd7: rst(); break;
|
case 0xd7: rst(); break;
|
||||||
|
case 0xd8: ret(); break;
|
||||||
|
case 0xda: jp16(); break;
|
||||||
case 0xdc: call(); break;
|
case 0xdc: call(); break;
|
||||||
case 0xde: sbc8(); break;
|
case 0xde: sbc8(); break;
|
||||||
case 0xdf: rst(); break;
|
case 0xdf: rst(); break;
|
||||||
@@ -268,12 +291,15 @@ void CPU::update()
|
|||||||
case 0xe6: and8(); break;
|
case 0xe6: and8(); break;
|
||||||
case 0xe7: rst(); break;
|
case 0xe7: rst(); break;
|
||||||
case 0xe8: adds8(); break;
|
case 0xe8: adds8(); break;
|
||||||
|
case 0xe9: jp16(); break;
|
||||||
case 0xea: ldr8(); break;
|
case 0xea: ldr8(); break;
|
||||||
|
case 0xee: xor8(); break;
|
||||||
case 0xef: rst(); break;
|
case 0xef: rst(); break;
|
||||||
case 0xf0: ldffi8(); break;
|
case 0xf0: ldffi8(); break;
|
||||||
case 0xf1: pop(); break;
|
case 0xf1: pop(); break;
|
||||||
case 0xf2: lda8(); break;
|
case 0xf2: lda8(); break;
|
||||||
case 0xf5: push(); break;
|
case 0xf5: push(); break;
|
||||||
|
case 0xf6: or8(); break;
|
||||||
case 0xf7: rst(); break;
|
case 0xf7: rst(); break;
|
||||||
case 0xf8: ldr16(); break;
|
case 0xf8: ldr16(); break;
|
||||||
case 0xf9: ldr16(); break;
|
case 0xf9: ldr16(); break;
|
||||||
@@ -566,6 +592,50 @@ void CPU::inc8()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPU::or8()
|
||||||
|
{
|
||||||
|
auto bitwise_or = [this](uint32_t register_) {
|
||||||
|
// OR r8, flags: Z 0 0 0
|
||||||
|
m_wait_cycles += 4;
|
||||||
|
|
||||||
|
// Set flags
|
||||||
|
m_nf = m_hf = m_cf = 0;
|
||||||
|
|
||||||
|
// Store into A the bitwise OR of the value in r8 and A
|
||||||
|
m_a = m_a | register_;
|
||||||
|
|
||||||
|
// Zero flag
|
||||||
|
m_zf = m_a == 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t opcode = pcRead();
|
||||||
|
switch (opcode) {
|
||||||
|
case 0xb0: /* OR A,B */ bitwise_or(m_b); break;
|
||||||
|
case 0xb1: /* OR A,C */ bitwise_or(m_c); break;
|
||||||
|
case 0xb2: /* OR A,D */ bitwise_or(m_d); break;
|
||||||
|
case 0xb3: /* OR A,E */ bitwise_or(m_e); break;
|
||||||
|
case 0xb4: /* OR A,H */ bitwise_or(m_h); break;
|
||||||
|
case 0xb5: /* OR A,L */ bitwise_or(m_l); break;
|
||||||
|
case 0xb6: /* OR A,(HL) */ {
|
||||||
|
m_wait_cycles += 4; // + 4 = 8 total
|
||||||
|
|
||||||
|
// Store into A the bitwise OR of the byte pointed to by HL and A
|
||||||
|
bitwise_or(read(hl()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xb7: /* OR A,A */ bitwise_or(m_a); break;
|
||||||
|
case 0xf6: /* OR A,i8 */ {
|
||||||
|
m_wait_cycles += 4; // + 4 = 8 total
|
||||||
|
|
||||||
|
// Store into A the bitwise OR of i8 and A
|
||||||
|
bitwise_or(pcRead());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CPU::sbc8()
|
void CPU::sbc8()
|
||||||
{
|
{
|
||||||
auto subtract_carry = [this](uint32_t register_) -> void {
|
auto subtract_carry = [this](uint32_t register_) -> void {
|
||||||
@@ -664,18 +734,43 @@ void CPU::sub8()
|
|||||||
|
|
||||||
void CPU::xor8()
|
void CPU::xor8()
|
||||||
{
|
{
|
||||||
|
auto bitwise_xor = [this](uint32_t register_) {
|
||||||
|
// XOR r8, flags: Z 0 0 0
|
||||||
|
m_wait_cycles += 4;
|
||||||
|
|
||||||
|
// Set flags
|
||||||
|
m_nf = m_hf = m_cf = 0;
|
||||||
|
|
||||||
|
// Bitwise XOR between the value in r8 and A
|
||||||
|
m_a = m_a ^ register_;
|
||||||
|
|
||||||
|
// Zero flag
|
||||||
|
m_zf = m_a == 0;
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t opcode = pcRead();
|
uint8_t opcode = pcRead();
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0xa8: // XOR B, flags: Z 0 0 0
|
case 0xa8: /* XOR A,B */ bitwise_xor(m_b); break;
|
||||||
m_nf = m_hf = m_cf = 0;
|
case 0xa9: /* XOR A,C */ bitwise_xor(m_c); break;
|
||||||
m_a ^= m_b;
|
case 0xaa: /* XOR A,D */ bitwise_xor(m_d); break;
|
||||||
m_zf = m_a == 0;
|
case 0xab: /* XOR A,E */ bitwise_xor(m_e); break;
|
||||||
|
case 0xac: /* XOR A,H */ bitwise_xor(m_h); break;
|
||||||
|
case 0xad: /* XOR A,L */ bitwise_xor(m_l); break;
|
||||||
|
case 0xae: /* XOR A,(HL) */ {
|
||||||
|
m_wait_cycles += 4; // + 4 = 8 total
|
||||||
|
|
||||||
|
// Bitwise XOR between the byte pointed to by HL and A
|
||||||
|
bitwise_xor(read(hl()));
|
||||||
break;
|
break;
|
||||||
case 0xaf: // XOR A, flags: 1 0 0 0
|
}
|
||||||
// A ^ A will always be 0
|
case 0xaf: /* XOR A,A */ bitwise_xor(m_a); break;
|
||||||
m_a = m_nf = m_hf = m_cf = 0;
|
case 0xee: /* XOR A,i8 */ {
|
||||||
m_zf = 1;
|
m_wait_cycles += 4; // + 4 = 8 total
|
||||||
|
|
||||||
|
// Bitwise XOR between the value in i8 and A
|
||||||
|
bitwise_xor(pcRead());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
@@ -1276,11 +1371,34 @@ void CPU::call()
|
|||||||
|
|
||||||
void CPU::jp16()
|
void CPU::jp16()
|
||||||
{
|
{
|
||||||
|
auto jump = [this](bool should_jump) -> void {
|
||||||
|
// JP cc,i16
|
||||||
|
|
||||||
|
// Note: the operand is read even when the condition is false
|
||||||
|
uint32_t data = pcRead16();
|
||||||
|
|
||||||
|
if (!should_jump) {
|
||||||
|
m_wait_cycles += 12;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_wait_cycles += 16;
|
||||||
|
|
||||||
|
// Jump to address i16 if condition is met; effectively, store i16 into PC
|
||||||
|
m_pc = data;
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t opcode = pcRead();
|
uint8_t opcode = pcRead();
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0xc3: // JP a16
|
case 0xc2: /* JP NZ,a16 */ jump(!m_zf); break;
|
||||||
m_wait_cycles += 16;
|
case 0xc3: /* JP a16 */ jump(true); break;
|
||||||
m_pc = pcRead16();
|
case 0xca: /* JP Z,a16 */ jump(m_zf); break;
|
||||||
|
case 0xd2: /* JP NC,a16 */ jump(!m_cf); break;
|
||||||
|
case 0xda: /* JP C,a16 */ jump(m_cf); break;
|
||||||
|
case 0xe9: // JP HL
|
||||||
|
m_wait_cycles += 4;
|
||||||
|
|
||||||
|
// Jump to address in HL; effectively, load PC with value in register HL
|
||||||
|
m_pc = hl();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
@@ -1302,7 +1420,7 @@ void CPU::jrs8()
|
|||||||
m_wait_cycles += 12;
|
m_wait_cycles += 12;
|
||||||
|
|
||||||
// Relative jump by adding s8 to the address of the instruction following the JR
|
// Relative jump by adding s8 to the address of the instruction following the JR
|
||||||
m_pc = m_pc + signed_data;
|
m_pc = (m_pc + signed_data) & 0xffff;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t opcode = pcRead();
|
uint8_t opcode = pcRead();
|
||||||
@@ -1317,6 +1435,38 @@ void CPU::jrs8()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPU::ret()
|
||||||
|
{
|
||||||
|
auto function_return = [this](bool should_call) -> void {
|
||||||
|
// RET cc,i16
|
||||||
|
|
||||||
|
if (!should_call) {
|
||||||
|
m_wait_cycles += 8;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_wait_cycles += 20;
|
||||||
|
|
||||||
|
// Return from subroutine if condition cc is met,
|
||||||
|
// this is basically a POP PC (if such an instruction existed)
|
||||||
|
m_pc = read(m_sp);
|
||||||
|
m_sp = (m_sp + 1) & 0xffff;
|
||||||
|
m_pc = m_pc | (read(m_sp) << 8);
|
||||||
|
m_sp = (m_sp + 1) & 0xffff;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t opcode = pcRead();
|
||||||
|
switch (opcode) {
|
||||||
|
case 0xc0: /* RET NZ,i16 */ function_return(!m_nf); break;
|
||||||
|
case 0xc8: /* RET Z,i16 */ function_return(m_nf); break;
|
||||||
|
case 0xc9: /* RET i16 */ function_return(true); break;
|
||||||
|
case 0xd0: /* RET NC,i16 */ function_return(!m_cf); break;
|
||||||
|
case 0xd8: /* RET C,i16 */ function_return(m_cf); break;
|
||||||
|
// case 0xd9: /* RETI */ FIXME break;
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CPU::rst()
|
void CPU::rst()
|
||||||
{
|
{
|
||||||
auto function_call = [this](uint32_t fixed_address) -> void {
|
auto function_call = [this](uint32_t fixed_address) -> void {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public:
|
|||||||
void cp();
|
void cp();
|
||||||
void dec8();
|
void dec8();
|
||||||
void inc8();
|
void inc8();
|
||||||
|
void or8();
|
||||||
void sbc8();
|
void sbc8();
|
||||||
void sub8();
|
void sub8();
|
||||||
void xor8();
|
void xor8();
|
||||||
@@ -85,6 +86,7 @@ public:
|
|||||||
void call();
|
void call();
|
||||||
void jp16();
|
void jp16();
|
||||||
void jrs8();
|
void jrs8();
|
||||||
|
void ret();
|
||||||
void rst();
|
void rst();
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user