add some 0xcb extended instructions

This commit is contained in:
Matt Laux 2019-04-19 23:07:45 -05:00
parent 79c42f6397
commit cde73e301a
3 changed files with 103 additions and 4 deletions

101
src/cpu.c
View File

@ -175,6 +175,16 @@ static void xor(struct cpu *regs, u8 value)
clear_flag(regs, FLAG_CARRY);
}
static void or(struct cpu *regs, u8 value)
{
regs->a |= value;
if(regs->a == 0)
set_flag(regs, FLAG_ZERO);
clear_flag(regs, FLAG_SIGN);
clear_flag(regs, FLAG_HALF_CARRY);
clear_flag(regs, FLAG_CARRY);
}
static void push(struct cpu *cpu, u16 value)
{
write16(cpu, cpu->sp - 2, value & 0xff);
@ -207,12 +217,71 @@ static u16 add16(struct cpu *cpu, u16 src)
return total & 0xffff;
}
static u8 read_reg(struct cpu *cpu, int index)
{
switch (index) {
case 0: return cpu->b;
case 1: return cpu->c;
case 2: return cpu->d;
case 3: return cpu->e;
case 4: return cpu->h;
case 5: return cpu->l;
case 6: return read8(cpu, read_hl(cpu));
case 7: return cpu->a;
default: cpu_panic(cpu);
}
}
static u8 write_reg(struct cpu *cpu, int index, u8 val)
{
switch (index) {
case 0: cpu->b = val; break;
case 1: cpu->c = val; break;
case 2: cpu->d = val; break;
case 3: cpu->e = val; break;
case 4: cpu->h = val; break;
case 5: cpu->l = val; break;
case 6: write8(cpu, read_hl(cpu), val); break;
case 7: cpu->a = val; break;
default: cpu_panic(cpu);
}
}
static void extended_insn(struct cpu *cpu, u8 insn)
{
u8 temp;
int op = insn >> 6;
int bit = (insn >> 3) & 0x7;
int reg = insn & 0x7;
switch (op) {
case 0:
break;
case 1: // BIT
temp = read_reg(cpu, reg);
if ((temp & (1 << bit)) == 0) {
set_flag(cpu, FLAG_ZERO);
} else {
clear_flag(cpu, FLAG_ZERO);
}
clear_flag(cpu, FLAG_SIGN);
set_flag(cpu, FLAG_HALF_CARRY);
break;
case 2: // RES
break;
case 3: // SET
break;
}
}
void cpu_step(struct cpu *cpu)
{
u8 temp;
u16 temp16;
u8 opc = cpu->mem_read(cpu->mem_model, cpu->pc);
printf("0x%04x %s\n", cpu->pc, instructions[opc].format);
cpu->pc++;
if (cpu->pc == 0x100) exit(0);
switch (opc) {
case 0: // NOP
break;
@ -386,15 +455,25 @@ void cpu_step(struct cpu *cpu)
cpu->pc = pop(cpu);
break;
case 0xcd: // CALL a16
temp = read16(cpu, cpu->pc);
temp16 = read16(cpu, cpu->pc);
cpu->pc += 2;
push(cpu, cpu->pc);
cpu->pc = temp;
cpu->pc = temp16;
break;
case 0xc3: // JP a16
cpu->pc = read16(cpu, cpu->pc);
break;
// OR
case 0xb0: or(cpu, cpu->b); break;
case 0xb1: or(cpu, cpu->c); break;
case 0xb2: or(cpu, cpu->d); break;
case 0xb3: or(cpu, cpu->e); break;
case 0xb4: or(cpu, cpu->h); break;
case 0xb5: or(cpu, cpu->l); break;
case 0xb6: or(cpu, read8(cpu, read_hl(cpu))); break;
case 0xb7: or(cpu, cpu->a); break;
// XOR
case 0xa8: xor(cpu, cpu->b); break;
case 0xa9: xor(cpu, cpu->c); break;
@ -405,7 +484,21 @@ void cpu_step(struct cpu *cpu)
case 0xae: xor(cpu, read8(cpu, read_hl(cpu))); break;
case 0xaf: xor(cpu, cpu->a); break;
case 0xee: xor(cpu, read8(cpu, cpu->pc)); cpu->pc++; break;
// RST
case 0xc7: push(cpu, cpu->pc); cpu->pc = 0x00; break;
case 0xcf: push(cpu, cpu->pc); cpu->pc = 0x08; break;
case 0xd7: push(cpu, cpu->pc); cpu->pc = 0x10; break;
case 0xdf: push(cpu, cpu->pc); cpu->pc = 0x18; break;
case 0xe7: push(cpu, cpu->pc); cpu->pc = 0x20; break;
case 0xef: push(cpu, cpu->pc); cpu->pc = 0x28; break;
case 0xf7: push(cpu, cpu->pc); cpu->pc = 0x30; break;
case 0xff: push(cpu, cpu->pc); cpu->pc = 0x38; break;
case 0xcb:
extended_insn(cpu, read8(cpu, cpu->pc));
cpu->pc++;
break;
case 0xe0: // LDH (a8),A
write16(cpu, 0xff00 + read8(cpu, cpu->pc), cpu->a);
cpu->pc++;
@ -428,6 +521,8 @@ void cpu_step(struct cpu *cpu)
break;
case 0xf3: // DI
break;
case 0xfb: // EI
break;
default:
printf("unknown opcode 0x%02x %s\n", opc, instructions[opc].format);
cpu_panic(cpu);

View File

@ -4,6 +4,7 @@
#include "rom.h"
#include "dmg.h"
#include "types.h"
#include "bootstrap.h"
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom)
{
@ -14,6 +15,9 @@ void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom)
u8 dmg_read(void *_dmg, u16 address)
{
struct dmg *dmg = (struct dmg *) _dmg;
if (address < 0x100) {
return dmg_boot_rom[address];
}
if (address < 0x4000) {
return dmg->rom->data[address];
} else if (address < 0x8000) {

View File

@ -26,7 +26,7 @@ int main(int argc, char *argv[])
dmg_new(&dmg, &cpu, &rom);
cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
cpu.pc = 0x100;
cpu.pc = 0;
while (1) {
cpu_step(&cpu);