Compare commits

..
3 Commits
Author SHA1 Message Date
Riyyi baa679904c Emulator: Implement RET opcodes, minus one 2022-08-29 01:54:31 +02:00
Riyyi 0c4d7b2112 Emulator: Implement JP opcodes 2022-08-29 01:31:02 +02:00
Riyyi 3346b5329a Emulator: Implement XOR/OR opcodes 2022-08-29 01:12:59 +02:00
2 changed files with 164 additions and 12 deletions
+162 -12
View File
@@ -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 {
+2
View File
@@ -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();
// ------------------------------------- // -------------------------------------