Compare commits

..
8 Commits
2 changed files with 185 additions and 66 deletions
+177 -56
View File
@@ -57,33 +57,45 @@ void CPU::update()
m_wait_cycles--;
if (m_wait_cycles <= 0) {
// Read next opcode
uint8_t opcode = peekMemory();
uint8_t opcode = read(m_pc);
print("running opcode: {:#x}\n", opcode);
switch (opcode) {
case 0x01: ld16(); break;
case 0x02: ld8(); break;
case 0x06: ld8(); break;
case 0x08: ld16(); break;
case 0x11: ld16(); break;
case 0x12: ld8(); break;
case 0x16: ld8(); break;
case 0x21: ld16(); break;
case 0x22: ld8(); break;
case 0x26: ld8(); break;
case 0x31: ld16(); break;
case 0x32: ld8(); break;
case 0x36: ld8(); break;
case 0x3e: ld8(); break;
case 0xa8: xor8(); break;
case 0xaf: xor8(); break;
case 0xc3: jp16(); break;
case 0xc6: add(); break;
case 0xcd: call(); break;
case 0xe0: ldh8(); break;
case 0xf0: ldh8(); break;
case 0xf8: ld16(); break;
case 0xf9: ld16(); break;
default:
print("opcode {:#x} not implemented", opcode);
print("opcode {:#x} not implemented\n", opcode);
VERIFY_NOT_REACHED();
}
}
// print("This is an update from the CPU\n");
}
void CPU::add()
{
uint8_t opcode = consumeMemory();
uint8_t immediate = consumeMemory();
uint8_t opcode = pcRead();
uint8_t immediate = pcRead();
switch (opcode) {
case 0xc6:
// ADD A,d8
@@ -99,7 +111,28 @@ void CPU::add()
m_a += immediate;
// Drop overflown bits, the 'A' register is 8-bit
m_a &= 0xff;
m_a &= 0x00ff;
break;
default:
VERIFY_NOT_REACHED();
}
}
void CPU::xor8()
{
uint8_t opcode = pcRead();
switch (opcode) {
case 0xa8:
// XOR B, flags: Z 0 0 0
m_nf = m_hf = m_cf = 0;
m_a ^= m_b;
m_zf = m_a == 0;
break;
case 0xaf:
// XOR A, flags: 1 0 0 0
// A^A will always be 0
m_a = m_nf = m_hf = m_cf = 0;
m_zf = 1;
break;
default:
VERIFY_NOT_REACHED();
@@ -108,11 +141,70 @@ void CPU::add()
void CPU::ld8()
{
uint8_t opcode = consumeMemory();
uint8_t opcode = pcRead();
switch (opcode) {
case 0x3e:
case 0x02:
// LD (BC),A
m_wait_cycles += 8;
m_a = immediate8();
write(bc(), m_a);
break;
case 0x06:
// LD B,n
m_wait_cycles += 8;
m_b = pcRead();
break;
case 0x12:
// LD (DE),A
m_wait_cycles += 8;
write(de(), m_a);
break;
case 0x16:
// LD D,n
m_wait_cycles += 8;
m_d = pcRead();
break;
case 0x22: {
// LD (HL+),A == LD (HLI),A == LDI (HL),A
m_wait_cycles += 8;
// Put A into memory address in HL
uint32_t address = hl();
write(address, m_a);
// Increment HL
address = (address + 1) & 0xffff;
m_l = address & 0x00ff;
m_h = address >> 8;
break;
}
case 0x26:
// LD H,n
m_wait_cycles += 8;
m_h = pcRead();
break;
case 0x32: {
// LD (HL-),A == LD (HLD),A == LDD (HL),A
m_wait_cycles += 8;
// Put A into memory address in HL
uint32_t address = hl();
write(address, m_a);
// Decrement HL
address = (address - 1) & 0xffff;
m_l = address & 0x00ff;
m_h = address >> 8;
break;
}
case 0x36:
// LD (HL),n
m_wait_cycles += 12;
write(hl(), pcRead());
break;
case 0x3e:
// LD A,n
m_wait_cycles += 8;
m_a = pcRead();
break;
default:
VERIFY_NOT_REACHED();
@@ -121,19 +213,21 @@ void CPU::ld8()
void CPU::ldh8()
{
uint8_t opcode = consumeMemory();
uint8_t opcode = pcRead();
switch (opcode) {
case 0xe0:
// LD ($ff00 + n),A == LDH (n),A
// Put value in A into address (0xff00 + next byte in memory):
m_wait_cycles += 12;
writeFf(m_a);
// Put value in A into address (0xff00 + next byte in memory)
ffWrite(pcRead(), m_a);
break;
case 0xf0:
// LD A,($ff00 + n) == LDH A,(n)
// Put value at address (0xff00 + next byte in memory) into A:
m_wait_cycles += 12;
m_a = readFf();
// Put value at address (0xff00 + next byte in memory) into A
m_a = ffRead(pcRead());
break;
default:
VERIFY_NOT_REACHED();
@@ -142,38 +236,50 @@ void CPU::ldh8()
void CPU::ld16()
{
uint8_t opcode = consumeMemory();
uint8_t opcode = pcRead();
switch (opcode) {
case 0x01: {
m_wait_cycles += 12;
setBc(immediate16());
break;
}
case 0x11:
m_wait_cycles += 12;
setDe(immediate16());
break;
case 0x21:
m_wait_cycles += 12;
setHl(immediate16());
break;
case 0x31: {
m_wait_cycles += 12;
m_sp = immediate16();
write(bc(), pcRead16());
break;
}
case 0x08: {
// LD (nn),SP
m_wait_cycles += 20;
// Put value of SP into address given by next 2 bytes in memory
// TODO
break;
}
case 0xf8: {
case 0x11:
// LD DE,nn
m_wait_cycles += 12;
write(de(), pcRead16());
break;
case 0x21:
// LD HL,nn
m_wait_cycles += 12;
write(hl(), pcRead16());
break;
case 0x31: {
// LD SP,nn
m_wait_cycles += 12;
m_sp = pcRead16();
break;
}
case 0xf8: {
// LD HL,SP + e8 == LDHL SP,e8
m_wait_cycles += 12;
// Put SP + next (signed) byte in memory into HL
// TODO
// Unsets ZF and NF, may enable HF and CF
// TODO flags
break;
}
case 0xf9: {
// LD SP,HL
m_wait_cycles += 8;
m_sp = hl();
break;
@@ -183,13 +289,39 @@ void CPU::ld16()
}
}
void CPU::call()
{
uint8_t opcode = pcRead();
switch (opcode) {
case 0xcd: {
// CALL nn
m_wait_cycles += 24;
uint32_t data = pcRead16();
// Push address of next 2 bytes in memory onto stack
m_sp = (m_sp - 1) & 0xffff;
write(m_sp, data >> 8);
m_sp = (m_sp - 1) & 0xffff;
write(m_sp, data & 0x00ff);
// Jump to this address
m_pc = data;
break;
}
default:
VERIFY_NOT_REACHED();
}
}
void CPU::jp16()
{
uint8_t opcode = consumeMemory();
uint8_t opcode = pcRead();
switch (opcode) {
case 0xc3:
// JP nn
m_wait_cycles += 16;
m_pc = immediate16();
m_pc = pcRead16();
break;
default:
VERIFY_NOT_REACHED();
@@ -198,40 +330,29 @@ void CPU::jp16()
// -----------------------------------------
uint8_t CPU::peekMemory(int32_t offset) const
uint32_t CPU::pcRead()
{
return Emu::the().readMemory(m_pc + offset);
uint32_t data = Emu::the().readMemory(m_pc);
m_pc = (m_pc + 1) & 0xffff;
return data;
}
uint8_t CPU::consumeMemory()
void CPU::write(uint32_t address, uint32_t value)
{
return Emu::the().readMemory(m_pc++);
Emu::the().writeMemory(address, value);
}
void CPU::writeFf(uint32_t value)
uint32_t CPU::read(uint32_t address)
{
Emu::the().writeMemory(immediate8() | (0xff << 8), value);
return Emu::the().readMemory(address);
}
uint32_t CPU::readFf()
void CPU::ffWrite(uint32_t address, uint32_t value)
{
return Emu::the().readMemory(immediate8() | (0xff << 8));
Emu::the().writeMemory(address | (0xff << 8), value);
}
void CPU::setBc(uint32_t value)
uint32_t CPU::ffRead(uint32_t address)
{
m_b = value >> 8;
m_c = value;
}
void CPU::setDe(uint32_t value)
{
m_d = value >> 8;
m_e = value;
}
void CPU::setHl(uint32_t value)
{
m_h = value >> 8;
m_l = value;
return Emu::the().readMemory(address | (0xff << 8));
}
+8 -10
View File
@@ -25,6 +25,7 @@ public:
// 8-bit
void add();
void xor8();
// 16-bit
@@ -47,6 +48,7 @@ public:
// -------------------------------------
// Jumps and Subroutines
void call();
void jp16();
// -------------------------------------
@@ -56,18 +58,14 @@ public:
// Miscellaneous Instructions
private:
uint8_t peekMemory(int32_t offset = 0) const;
uint8_t consumeMemory();
uint32_t pcRead();
uint32_t pcRead16() { return pcRead() | (pcRead() << 8); }
uint32_t immediate8() { return consumeMemory(); }
uint32_t immediate16() { return consumeMemory() | (consumeMemory() << 8); }
void write(uint32_t address, uint32_t value);
uint32_t read(uint32_t address);
void writeFf(uint32_t value);
uint32_t readFf();
void setBc(uint32_t value);
void setDe(uint32_t value);
void setHl(uint32_t value);
void ffWrite(uint32_t address, uint32_t value);
uint32_t ffRead(uint32_t address);
uint32_t bc() const { return m_b << 8 | m_c; }
uint32_t de() const { return m_b << 8 | m_c; }