/* * A simulation of the LR35902 CPU used by the Nintendo Gameboy * * Author: Max Regan * Last Modified: 11-17-2015 */ #ifndef GB_CPU_H #define GB_CPU_H #include "gbemu/memory.h" #include #define CPU_F_BIT_POS_C 4 #define CPU_F_BIT_POS_H 5 #define CPU_F_BIT_POS_N 6 #define CPU_F_BIT_POS_Z 7 #define LR35902_MAX_EVENTS 16 typedef enum { LR35902_REG_BC = 0, LR35902_REG_DE = 1, LR35902_REG_HL = 2, LR35902_REG_AF = 3, LR35902_REG_SP, LR35902_REG_PC, NUM_LR35902_REGS_16 } lr35902_regs_16; typedef enum { LR35902_REG_B = 0, LR35902_REG_C = 1, LR35902_REG_D = 2, LR35902_REG_E = 3, LR35902_REG_H = 4, LR35902_REG_L = 5, LR35902_REG_HL_DEREF = 6, //Not a real register LR35902_REG_A = 7, //Accumulator LR35902_REG_F = 8, //Flags NUM_LR35902_REGS_8 } lr35902_regs_8; typedef enum { LR35902_INT_ON, LR35902_INT_OFF, } lr35902_interrupt_state; struct lr35902_state; typedef uint8_t (*lr35902_mem_read_fn)(struct lr35902_state *cpu, uint16_t address); typedef void (*lr35902_mem_write_fn)(struct lr35902_state *cpu, uint16_t address, uint8_t value); typedef void (*lr35902_instr)(struct lr35902_state *cpu, uint8_t instr); typedef void (*lr35902_cb_instr)(struct lr35902_state *cpu, uint8_t instr); typedef void (*lr35902_event_fn)(struct lr35902_state *cpu); struct lr35902_event { uint8_t cycles; lr35902_event_fn run; }; struct lr35902_state { struct gb_memory *memory; union { /* * As a convenience, give ourselves a bunch of different ways to * access the registers. They are carefully written below so they * overlap correctly, Per C99, as long as uint{8,16}_t are implemented, * there is guaranteed to be no padding and no trap representations. */ uint16_t regs_16[NUM_LR35902_REGS_16]; struct { uint16_t bc, de, hl, af, pc, sp; }; uint8_t regs_8[NUM_LR35902_REGS_8]; struct { uint8_t c, b, e, d, l, h, f_dummy, a; }; }; /* Only two operations access the flags as a collective, PUSH * AF and POP AF. It's much easier to represent them as * individual flags and combine them when needed */ int zf; int nf; int hf; int cf; int stall_cycles; int halted; void (*undef_d3)(struct lr35902_state *reg); lr35902_interrupt_state int_state; struct lr35902_event events[LR35902_MAX_EVENTS]; //Cool data struct { uint64_t cycles; uint64_t retired_instrs; uint64_t mem_reads; uint64_t mem_writes; } metrics; }; struct lr35902_ops { lr35902_mem_read_fn mem_read; lr35902_mem_write_fn mem_write; void (*undef_d3)(struct lr35902_state *reg); }; void lr35902_init(struct lr35902_state *cpu, struct gb_memory *memory, const struct lr35902_ops *ops); uint16_t lr35902_get_reg_16(const struct lr35902_state *cpu, lr35902_regs_16 reg); uint8_t lr35902_get_reg_8(const struct lr35902_state *cpu, lr35902_regs_8 reg); void lr35902_set_reg_16(struct lr35902_state *cpu, lr35902_regs_16 reg, uint16_t val); void lr35902_set_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg, uint8_t val); int lr35902_cycle(struct lr35902_state *cpu); #endif