mirror of
https://github.com/mlaux/gb6.git
synced 2025-01-23 02:33:00 +00:00
add some 0xcb extended instructions
This commit is contained in:
parent
79c42f6397
commit
cde73e301a
101
src/cpu.c
101
src/cpu.c
@ -175,6 +175,16 @@ static void xor(struct cpu *regs, u8 value)
|
|||||||
clear_flag(regs, FLAG_CARRY);
|
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)
|
static void push(struct cpu *cpu, u16 value)
|
||||||
{
|
{
|
||||||
write16(cpu, cpu->sp - 2, value & 0xff);
|
write16(cpu, cpu->sp - 2, value & 0xff);
|
||||||
@ -207,12 +217,71 @@ static u16 add16(struct cpu *cpu, u16 src)
|
|||||||
return total & 0xffff;
|
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)
|
void cpu_step(struct cpu *cpu)
|
||||||
{
|
{
|
||||||
u8 temp;
|
u8 temp;
|
||||||
|
u16 temp16;
|
||||||
u8 opc = cpu->mem_read(cpu->mem_model, cpu->pc);
|
u8 opc = cpu->mem_read(cpu->mem_model, cpu->pc);
|
||||||
printf("0x%04x %s\n", cpu->pc, instructions[opc].format);
|
printf("0x%04x %s\n", cpu->pc, instructions[opc].format);
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
|
if (cpu->pc == 0x100) exit(0);
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
case 0: // NOP
|
case 0: // NOP
|
||||||
break;
|
break;
|
||||||
@ -386,15 +455,25 @@ void cpu_step(struct cpu *cpu)
|
|||||||
cpu->pc = pop(cpu);
|
cpu->pc = pop(cpu);
|
||||||
break;
|
break;
|
||||||
case 0xcd: // CALL a16
|
case 0xcd: // CALL a16
|
||||||
temp = read16(cpu, cpu->pc);
|
temp16 = read16(cpu, cpu->pc);
|
||||||
cpu->pc += 2;
|
cpu->pc += 2;
|
||||||
push(cpu, cpu->pc);
|
push(cpu, cpu->pc);
|
||||||
cpu->pc = temp;
|
cpu->pc = temp16;
|
||||||
break;
|
break;
|
||||||
case 0xc3: // JP a16
|
case 0xc3: // JP a16
|
||||||
cpu->pc = read16(cpu, cpu->pc);
|
cpu->pc = read16(cpu, cpu->pc);
|
||||||
break;
|
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
|
// XOR
|
||||||
case 0xa8: xor(cpu, cpu->b); break;
|
case 0xa8: xor(cpu, cpu->b); break;
|
||||||
case 0xa9: xor(cpu, cpu->c); 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 0xae: xor(cpu, read8(cpu, read_hl(cpu))); break;
|
||||||
case 0xaf: xor(cpu, cpu->a); break;
|
case 0xaf: xor(cpu, cpu->a); break;
|
||||||
case 0xee: xor(cpu, read8(cpu, cpu->pc)); cpu->pc++; 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
|
case 0xe0: // LDH (a8),A
|
||||||
write16(cpu, 0xff00 + read8(cpu, cpu->pc), cpu->a);
|
write16(cpu, 0xff00 + read8(cpu, cpu->pc), cpu->a);
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
@ -428,6 +521,8 @@ void cpu_step(struct cpu *cpu)
|
|||||||
break;
|
break;
|
||||||
case 0xf3: // DI
|
case 0xf3: // DI
|
||||||
break;
|
break;
|
||||||
|
case 0xfb: // EI
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("unknown opcode 0x%02x %s\n", opc, instructions[opc].format);
|
printf("unknown opcode 0x%02x %s\n", opc, instructions[opc].format);
|
||||||
cpu_panic(cpu);
|
cpu_panic(cpu);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
#include "dmg.h"
|
#include "dmg.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "bootstrap.h"
|
||||||
|
|
||||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom)
|
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)
|
u8 dmg_read(void *_dmg, u16 address)
|
||||||
{
|
{
|
||||||
struct dmg *dmg = (struct dmg *) _dmg;
|
struct dmg *dmg = (struct dmg *) _dmg;
|
||||||
|
if (address < 0x100) {
|
||||||
|
return dmg_boot_rom[address];
|
||||||
|
}
|
||||||
if (address < 0x4000) {
|
if (address < 0x4000) {
|
||||||
return dmg->rom->data[address];
|
return dmg->rom->data[address];
|
||||||
} else if (address < 0x8000) {
|
} else if (address < 0x8000) {
|
||||||
|
@ -26,7 +26,7 @@ int main(int argc, char *argv[])
|
|||||||
dmg_new(&dmg, &cpu, &rom);
|
dmg_new(&dmg, &cpu, &rom);
|
||||||
cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
|
cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
|
||||||
|
|
||||||
cpu.pc = 0x100;
|
cpu.pc = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
cpu_step(&cpu);
|
cpu_step(&cpu);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user