diff --git a/src/gbemu/cpu.c b/src/gbemu/cpu.c index c0de148..f92dd00 100644 --- a/src/gbemu/cpu.c +++ b/src/gbemu/cpu.c @@ -5,382 +5,23 @@ #include #include +#include #include "gbemu/cpu.h" #include "common/common.h" -#define WRITE_BIT(x, idx, bit) \ - do {(x) &= (~(1 << (idx)) | ((bit) << (idx)));} while(0) #define SET_BIT(x, idx) do {(x) |= (1 << (idx));} while (0) #define CLR_BIT(x, idx) do {(x) &= ~(1 << (idx));} while (0) #define GET_BIT(x, bit) (((x) >> (bit)) & 1) +#define WRITE_BIT(x, idx, bit) \ + do {(x) &= (~(1 << (idx)) | ((bit) << (idx)));} while(0) -/*TODO: Timings are all totally boned */ -/* Primary instructions */ -static void nop(struct lr35902_state *cpu, uint8_t instr); -static void ld(struct lr35902_state *cpu, uint8_t instr); -static void ld_deref(struct lr35902_state *cpu, uint8_t instr); -static void ld_into_deref(struct lr35902_state *cpu, uint8_t instr); -static void ld_d8(struct lr35902_state *cpu, uint8_t instr); -static void ld_d16(struct lr35902_state *cpu, uint8_t instr); -static void ld_a16(struct lr35902_state *cpu, uint8_t instr); -static void ld_c_offset(struct lr35902_state *cpu, uint8_t instr); -static void ld_hl_d16(struct lr35902_state *cpu, uint8_t inst); -static void inc(struct lr35902_state *cpu, uint8_t instr); -static void inc_16(struct lr35902_state *cpu, uint8_t instr); -static void dec(struct lr35902_state *cpu, uint8_t instr); -static void dec_16(struct lr35902_state *cpu, uint8_t instr); -static void rlca(struct lr35902_state *cpu, uint8_t instr); -static void add(struct lr35902_state *cpu, uint8_t instr); -static void rrca(struct lr35902_state *cpu, uint8_t instr); -static void stop(struct lr35902_state *cpu, uint8_t instr); -static void rla(struct lr35902_state *cpu, uint8_t instr); -static void jr(struct lr35902_state *cpu, uint8_t instr); -static void jr_cond(struct lr35902_state *cpu, uint8_t instr); -static void rra(struct lr35902_state *cpu, uint8_t instr); -static void daa(struct lr35902_state *cpu, uint8_t instr); -static void cpl(struct lr35902_state *cpu, uint8_t instr); -static void scf(struct lr35902_state *cpu, uint8_t instr); -static void ccf(struct lr35902_state *cpu, uint8_t instr); -static void halt(struct lr35902_state *cpu, uint8_t instr); -static void adc(struct lr35902_state *cpu, uint8_t instr); -static void sub(struct lr35902_state *cpu, uint8_t instr); -static void sbc(struct lr35902_state *cpu, uint8_t instr); -static void and(struct lr35902_state *cpu, uint8_t instr); -static void xor(struct lr35902_state *cpu, uint8_t instr); -static void or(struct lr35902_state *cpu, uint8_t instr); -static void cp(struct lr35902_state *cpu, uint8_t instr); -static void ret(struct lr35902_state *cpu, uint8_t instr); -static void pop(struct lr35902_state *cpu, uint8_t instr); -static void jp(struct lr35902_state *cpu, uint8_t instr); -static void jp_a16(struct lr35902_state *cpu, uint8_t instr); -static void jp_d8(struct lr35902_state *cpu, uint8_t instr); -static void call(struct lr35902_state *cpu, uint8_t instr); -static void push(struct lr35902_state *cpu, uint8_t instr); -static void add_d8(struct lr35902_state *cpu, uint8_t instr); -static void rst(struct lr35902_state *cpu, uint8_t instr); -static void cb_prefix(struct lr35902_state *cpu, uint8_t instr); -static void adc_d8(struct lr35902_state *cpu, uint8_t instr); -static void undef(struct lr35902_state *cpu, uint8_t instr); -static void sub_d8(struct lr35902_state *cpu, uint8_t instr); -static void reti(struct lr35902_state *cpu, uint8_t instr); -static void sbc_d8(struct lr35902_state *cpu, uint8_t instr); -static void ldh(struct lr35902_state *cpu, uint8_t instr); -static void and_d8(struct lr35902_state *cpu, uint8_t instr); -static void xor_d8(struct lr35902_state *cpu, uint8_t instr); -static void di(struct lr35902_state *cpu, uint8_t instr); -static void or_d8(struct lr35902_state *cpu, uint8_t instr); -static void ei(struct lr35902_state *cpu, uint8_t instr); -static void cp_d8(struct lr35902_state *cpu, uint8_t instr); +#define CALC_H_ADD(a, b) ((((a) & 0xf) + ((b) & 0xf)) > 0xf) +#define CALC_H_SUB(a, b) (((a) & 0xf) < ((b) & 0xf)) -/* C-u M-x align-regexp \(,\) RET RET y */ -lr35902_instr lr35902_instrs[] = { - /*0x0?*/ - nop, - ld_d16, - ld_into_deref, - inc_16, - inc, - dec, - ld_d8, - rlca, - ld, - add, - ld, - dec_16, - inc, - dec, - ld_d8, - rrca, - /*0x1?*/ - stop, - ld_d16, - ld_into_deref, - inc_16, - inc, - dec, - ld_d8, - rla, - jr, - add, - ld_deref, - dec_16, - inc, - dec, - ld_d8, - rra, - /*0x2?*/ - jr_cond, - ld_d16, - ld_deref, - inc_16, - inc, - dec, - ld_d8, - daa, - jr_cond, - add, - ld_hl_d16, - dec_16, - inc, - dec, - ld_d8, - cpl, - /*0x3?*/ - jr_cond, - ld_d16, - ld_deref, - inc_16, - inc, - dec, - ld_d8, - scf, - jr_cond, - add, - ld, - dec_16, - inc, - dec, - ld_d8, - ccf, - /*0x4?*/ - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - /*0x5?*/ - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - /*0x6?*/ - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - /*0x7?*/ - ld, - ld, - ld, - ld, - ld, - ld, - halt, - ld_into_deref, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - ld, - /*0x8?*/ - add, - add, - add, - add, - add, - add, - add, - add, - adc, - adc, - adc, - adc, - adc, - adc, - adc, - adc, - /*0x9?*/ - sub, - sub, - sub, - sub, - sub, - sub, - sub, - sub, - sbc, - sbc, - sbc, - sbc, - sbc, - sbc, - sbc, - sbc, - /*0xA?*/ - and, - and, - and, - and, - and, - and, - and, - and, - xor, - xor, - xor, - xor, - xor, - xor, - xor, - xor, - /*0xB?*/ - or, - or, - or, - or, - or, - or, - or, - or, - cp, - cp, - cp, - cp, - cp, - cp, - cp, - cp, - /*0xC?*/ - ret, - pop, - jp_a16, - jp_d8, - call, - push, - add_d8, - rst, - ret, - ret, - jp_a16, - cb_prefix, - call, - call, - adc_d8, - rst, - /*0xD?*/ - ret, - pop, - jp_a16, - undef, - call, - push, - sub_d8, - rst, - ret, - reti, - jp, - undef, - call, - undef, - sbc_d8, - rst, - /*0xE?*/ - ldh, - pop, - ld_c_offset, - undef, - undef, - push, - and_d8, - rst, - add, - jp, - ld_a16, - undef, - undef, - undef, - xor_d8, - rst, - /*0xF?*/ - ldh, - pop, - ld_c_offset, - di, - undef, - push, - or_d8, - rst, - ld, - ld, - ld_a16, - ei, - undef, - undef, - cp_d8, - rst, -}; - -/* CB-prefix functions*/ -static void rlc(struct lr35902_state *cpu, uint8_t instr); -static void rrc(struct lr35902_state *cpu, uint8_t instr); -static void rl(struct lr35902_state *cpu, uint8_t instr); -static void rr(struct lr35902_state *cpu, uint8_t instr); -static void sla(struct lr35902_state *cpu, uint8_t instr); -static void sra(struct lr35902_state *cpu, uint8_t instr); -static void swap(struct lr35902_state *cpu, uint8_t instr); -static void srl(struct lr35902_state *cpu, uint8_t instr); -static void bit(struct lr35902_state *cpu, uint8_t instr); -static void res(struct lr35902_state *cpu, uint8_t instr); -static void set(struct lr35902_state *cpu, uint8_t instr); - - -static lr35902_instr lr35902_cb_instrs[] = { - /*0x0?*/ rlc, rrc, - /*0x1?*/ rl, rr, - /*0x2?*/ sla, sra, - /*0x3?*/ swap, srl, - /*0x4?*/ bit, bit, - /*0x5?*/ bit, bit, - /*0x6?*/ bit, bit, - /*0x7?*/ bit, bit, - /*0x8?*/ res, res, - /*0x9?*/ res, res, - /*0xA?*/ res, res, - /*0xB?*/ res, res, - /*0xC?*/ set, set, - /*0xD?*/ set, set, - /*0xE?*/ set, set, - /*0xF?*/ set, set, -}; +#define CALC_C_ADD_16(a, b) (0xffff - (a) < (b)) +#define CALC_C_ADD_8(a, b) (0xff - (a) < (b)) +#define CALC_C_SUB(a, b) ((a) < (b)) static int cpu_reg16_to_idx[NUM_LR35902_REGS_16] = { [LR35902_REG_BC] = 0, @@ -409,8 +50,6 @@ static int cpu_reg8_to_idx[NUM_LR35902_REGS_8] = { [LR35902_REG_HL_DEREF] = -1, }; - - uint8_t lr35902_get_reg_8(const struct lr35902_state *cpu, lr35902_regs_8 reg) { ASSERT(reg < NUM_LR35902_REGS_8); @@ -423,7 +62,6 @@ void lr35902_set_reg_16(struct lr35902_state *cpu, lr35902_regs_16 reg, { ASSERT(reg < NUM_LR35902_REGS_16 && reg >= 0); cpu->regs_16[cpu_reg16_to_idx[reg]] = val; - lr3 } void lr35902_set_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg, @@ -433,80 +71,6 @@ void lr35902_set_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg, cpu->regs_8[cpu_reg8_to_idx[reg]] = val; } - -static void _incr_pc(struct lr35902_state *cpu) -{ - cpu->pc++; -} - -/* - * Runs any deferred events if it is their time to run - */ -static void _run_events(struct lr35902_state *cpu) -{ - int i; - for (i = 0; i < LR35902_MAX_EVENTS; i++) { - if (cpu->events[i].cycles == 1) { - cpu->events[i].run(cpu); - } - if (cpu->events[i].cycles > 0) { - cpu->events[i].cycles--; - } - } -} - -static void _schedule_event(struct lr35902_state *cpu, - lr35902_event_fn fn, uint8_t cycles) -{ - int i; - for (i = 0; i < LR35902_MAX_EVENTS; i++) { - if (cpu->events[i].cycles == 0) { - cpu->events[i].cycles = cycles; - cpu->events[i].run = fn; - return; - } - } - - _run_events(cpu); - cpu->halted=1; -} - -static void _enable_interrupts(struct lr35902_state *cpu) -{ - cpu->int_state = LR35902_INT_ON; -} - -static void _disable_interrupts(struct lr35902_state *cpu) -{ - cpu->int_state = LR35902_INT_OFF; -} - -static void _push_stack_8(struct lr35902_state *cpu, uint8_t val) -{ - cpu->mem_write(cpu, cpu->sp, val); - cpu->sp--; -} - -static void _push_stack_16(struct lr35902_state *cpu, uint16_t val) -{ - _push_stack_8(cpu, val >> 8); - _push_stack_8(cpu, val & 0xFF); -} - -static uint8_t _pop_stack_8(struct lr35902_state *cpu) -{ - return cpu->mem_read(cpu, cpu->sp++); -} - -static uint16_t _pop_stack_16(struct lr35902_state *cpu) -{ - uint16_t val; - val = _pop_stack_8(cpu); - val |= _pop_stack_8(cpu) << 8; - - return val; -} - void lr35902_init(struct lr35902_state *cpu, lr35902_mem_read_fn mem_read, lr35902_mem_write_fn mem_write) @@ -535,934 +99,1253 @@ void lr35902_init(struct lr35902_state *cpu, cpu->metrics.mem_writes = 0; } +/* The shortest number of cycles each instruction may take. */ +static const unsigned int op_cycles[256] = { + /* 0x0_ */ 4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4, + /* 0x1_ */ 4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4, + /* 0x2_ */ 8, 12, 8, 8, 4, 4, 8, 4, 8, 8, 8, 8, 4, 4, 8, 4, + /* 0x3_ */ 8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4, + /* 0x4_ */ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, + /* 0x5_ */ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, + /* 0x6_ */ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, + /* 0x7_ */ 8, 8, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 8, 4, + + //FIXME + /* 0x0_ */ 4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4, + /* 0x1_ */ 4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4, + /* 0x2_ */ 8, 12, 8, 8, 4, 4, 8, 4, 8, 8, 8, 8, 4, 4, 8, 4, + /* 0x3_ */ 8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4, + /* 0x4_ */ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, + /* 0x5_ */ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, + /* 0x6_ */ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, + /* 0x7_ */ 8, 8, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 8, 4, + +}; + +static const unsigned int cb_op_cycles[256] = { 0 }; + + + +/* TODO: optimize macros with temp variables so mem_read() doesn't expand multiple times */ +#define INC_8(cpu, reg) \ + do { \ + (cpu)->nf = 0; \ + (cpu)->hf = CALC_H_ADD(reg, 1); \ + (reg)++; \ + (cpu)->zf = (reg) == 0; \ + } while (0) + +#define DEC_8(cpu, reg) \ + do { \ + (cpu)->nf = 1; \ + (cpu)->hf = CALC_H_SUB(reg, 1); \ + (reg)--; \ + (cpu)->zf = (reg) == 0; \ + } while (0) + +#define LD_D8(cpu, reg) \ + do { \ + (reg) = (cpu)->mem_read((cpu), (cpu)->pc++); \ + } while (0) + +#define LD_D16(cpu, reg) \ + do { \ + printf("LD_D16 " #reg "\n"); \ + (reg) = (cpu)->mem_read((cpu), (cpu)->pc++); \ + (reg) |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->pc++) << 8; \ + } while (0) + +#define ADD_8(cpu, dst, src) \ + do { \ + (cpu)->nf = 0; \ + (cpu)->hf = CALC_H_ADD((src), (dst)); \ + (dst) += (src); \ + (cpu)->zf = (dst) == 0; \ + } while (0) + +#define ADD_16(cpu, dst, src) \ + do { \ + (cpu)->nf = 0; \ + (cpu)->hf = CALC_H_ADD((dst), (src)); \ + (cpu)->cf = CALC_C_ADD_16((dst), (src)); \ + (dst) += (src); \ + } while (0) \ + +#define ADC_8(cpu, dst, src) \ + do { \ + /* FIXME flag generation */ \ + int tmp; \ + tmp = src + dst + cpu->cf; \ + cpu->nf = 0; \ + cpu->hf = CALC_H_ADD((src), (dst)); \ + (dst) = tmp; \ + cpu->zf = (dst) == 0; \ + } while (0) + +#define SUB_8(cpu, dst, src) \ + do { \ + int tmp; \ + tmp = dst - src; \ + cpu->nf = 1; \ + cpu->hf = CALC_H_SUB(src, dst); \ + dst = tmp; \ + cpu->zf = (dst) == 0; \ + } while (0) + +#define SBC_8(cpu, dst, src) \ + do { \ + /* FIXME flag generation */ \ + int tmp; \ + tmp = (dst) - (src) - 1; \ + (cpu)->nf = 1; \ + (cpu)->hf = CALC_H_ADD(src, dst); \ + (dst) = (tmp); \ + cpu->zf = (dst) == 0; \ + } while (0) + +#define AND_8(cpu, dst, src) \ + do { \ + (cpu)->nf = 0; \ + (cpu)->hf = 1; \ + (cpu)->cf = 0; \ + (dst) &= (src); \ + (cpu)->zf = ((dst) == 0); \ + } while (0) + +#define XOR_8(cpu, dst, src) \ + do { \ + (cpu)->nf = 0; \ + (cpu)->hf = 0; \ + (cpu)->cf = 0; \ + (dst) ^= (src); \ + (cpu)->zf = ((dst) == 0); \ + } while (0) + +#define OR_8(cpu, dst, src) \ + do { \ + (cpu)->nf = 0; \ + (cpu)->hf = 0; \ + (cpu)->cf = 0; \ + (dst) |= (src); \ + (cpu)->zf = ((dst) == 0); \ + } while (0) + +#define CP_8(cpu, dst, src) \ + do { \ + uint8_t _tmp; \ + (cpu)->nf = 1; \ + (cpu)->hf = CALC_H_SUB((dst), (src)); \ + (cpu)->cf = CALC_C_SUB((dst), (src)); \ + _tmp = (dst) - (src); \ + (cpu)->zf = ((_tmp) == 0); \ + } while (0) + + +#define JR_8(cpu) \ + do { \ + val_16 = cpu->mem_read(cpu, cpu->pc); \ + /* sign-extend */ \ + val_16 |= GET_BIT(val_16, 7) ? 0xff00 : 0; \ + cpu->pc += val_16; \ + } while (0) + +/* TODO: In general, check that we pop/push things correctly */ +#define POP_16(cpu, dst) \ + do { \ + (dst) = (cpu)->mem_read((cpu), (cpu)->sp++); \ + (dst) = (uint16_t) (cpu)->mem_read((cpu), (cpu)->sp++) << 8; \ + } while (0) + +#define PUSH_16(cpu, src) \ + do { \ + (cpu)->mem_write(cpu, --cpu->sp, src); \ + (cpu)->mem_write(cpu, --cpu->sp, src >> 8); \ + } while (0) + +#define CALL(cpu) \ + do { \ + cpu->mem_write(cpu, --cpu->sp, cpu->pc); \ + cpu->mem_write(cpu, --cpu->sp, cpu->pc >> 8); \ + cpu->pc = cpu->mem_read(cpu, cpu->pc++); \ + cpu->pc |= (uint16_t) cpu->mem_read(cpu, cpu->pc) << 8; \ + cpu->pc++; \ + } while (0) + +#define RET(cpu) \ + do { \ + (cpu)->pc = 0; \ + (cpu)->pc |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->sp--) << 8; \ + (cpu)->pc |= (cpu)->mem_read((cpu), (cpu)->sp--); \ + } while (0) + +#define RST(cpu, n) \ + do { \ + (cpu)->mem_write((cpu), (cpu)->sp++, (cpu)->pc >> 8); \ + (cpu)->mem_write((cpu), (cpu)->sp++, (cpu)->pc); \ + (cpu)->pc = (n); \ + } while (0); + void lr35902_cycle(struct lr35902_state *cpu) { - uint8_t instr = cpu->mem_read(cpu, cpu->pc); - cpu->metrics.cycles++; - if(cpu->stall_cycles > 0){ + uint8_t inst; + unsigned int cycles; + uint8_t val; + uint16_t val_16; + + if (cpu->stall_cycles > 0) { cpu->stall_cycles--; return; } - lr35902_instrs[instr](cpu, instr); - cpu->metrics.retired_instrs++; - cpu->pc++; - _run_events(cpu); - return; -} + inst = cpu->mem_read(cpu, cpu->pc++); + cycles = op_cycles[inst]; -static uint8_t _get_reg_8(struct lr35902_state *cpu, uint8_t reg){ - if (reg == LR35902_REG_HL_DEREF){ - return cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_HL)); - } else { - return cpu->regs_8[cpu_reg8_to_idx[reg]]; - } -} + printf("running command\n"); -static void _set_reg_8(struct lr35902_state *cpu, uint8_t reg, uint8_t val){ - ASSERT(reg < NUM_LR35902_REGS_8 && reg >= 0); - - if (reg == LR35902_REG_HL_DEREF){ - cpu->mem_write(cpu, lr35902_get_reg_16(cpu, LR35902_REG_HL), val); - } else { - cpu->regs_8[cpu_reg8_to_idx[reg]] = val; - } -} - -/************************/ -/* Primary instructions */ -/************************/ -static void nop(struct lr35902_state *cpu, uint8_t instr) -{ - return; -} - -static void ld(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val; - uint8_t src_reg, dst_reg; - - if (!(instr > 0x40 && instr <= 0x7F)) { - cpu->halted = 1; - return; - } - - dst_reg = (instr >> 3) & 7; - src_reg = instr & 7; - - val = _get_reg_8(cpu, src_reg); - _set_reg_8(cpu, dst_reg, val); -} - -static void ld_deref(struct lr35902_state *cpu, uint8_t instr) -{ - int incr = 0; - uint8_t val; - - switch(instr) { - /** Copy to Registers **/ - case 0x0A: - cpu->a = cpu->mem_read(cpu, cpu->bc); + switch (inst) { + case 0x00: /* NOP */ break; - case 0x1A: - cpu->a = cpu->mem_read(cpu, cpu->de); + case 0x01: /* LD BC, d16 */ + LD_D16(cpu, cpu->bc); break; - case 0x2A: - incr = 1; - /* Intentional fall-through */ - case 0x3A: - val = cpu->mem_read(cpu, cpu->hl); - cpu->a = val; - - if (incr) { - cpu->hl++; - } else { - cpu->hl--; - } - - lr35902_set_reg_16(cpu, LR35902_REG_HL, cpu->hl); - break; - - /** Copy to memory **/ - case 0x22: - incr = 1; - /* Intentional fall-through */ - case 0x32: - cpu->mem_write(cpu, cpu->hl, cpu->a); - - if (incr) { - cpu->hl++; - } else { - cpu->hl--; - } - - break; - case 0x12: - cpu->mem_write(cpu, cpu->de, cpu->a); - break; - case 0x02: + case 0x02: /* LD (BC), A */ cpu->mem_write(cpu, cpu->bc, cpu->a); break; - default: + case 0x03: /* INC BC */ + cpu->bc++; + break; + case 0x04: /* INC B */ + INC_8(cpu, cpu->b); + break; + case 0x05: /* DEC B */ + DEC_8(cpu, cpu->b); + break; + case 0x06: /* LD B, d8 */ + LD_D8(cpu, cpu->b); + break; + case 0x07: /* RLCA */ + cpu->cf = GET_BIT(cpu->a, 7); + cpu->nf = 0; + cpu->zf = 0; + cpu->hf = 0; + cpu->a <<= 1; + WRITE_BIT(cpu->a, 0, cpu->cf); + break; + case 0x08: /* LD (a16), SP */ + cpu->sp = cpu->mem_read(cpu, cpu->pc++); + cpu->sp |= cpu->mem_read(cpu, cpu->pc++) << 8; + break; + case 0x09: /* ADD HL, BC */ + ADD_16(cpu, cpu->hl, cpu->bc); + break; + case 0x0a: /* LD A, (BC) */ + cpu->a = cpu->mem_read(cpu, cpu->bc); + break; + case 0x0b: /* DEC, BC */ + cpu->bc--; + break; + case 0x0c: /* INC C */ + INC_8(cpu, cpu->c); + break; + case 0x0d: /* DEC C */ + DEC_8(cpu, cpu->d); + break; + case 0x0e: /* LD C, d8 */ + LD_D8(cpu, cpu->c); + break; + case 0x0f: /* RRCA */ + cpu->cf = GET_BIT(cpu->a, 0); + cpu->nf = 0; + cpu->zf = 0; + cpu->hf = 0; + cpu->a >>= 1; + WRITE_BIT(cpu->a, 7, cpu->cf); + break; + case 0x10: /* STOP */ + //TODO: + //cpu->stopped = true; + break; + case 0x11: /* LD DE, d16 */ + LD_D16(cpu, cpu->de); + break; + case 0x12: /* LD (DE), A */ + cpu->mem_write(cpu, cpu->de, cpu->a); + break; + case 0x13: /* INC DE */ + cpu->de++; + break; + case 0x14: /* INC D */ + INC_8(cpu, cpu->d); + break; + case 0x15: /* DEC D */ + DEC_8(cpu, cpu->d); + break; + case 0x16: /* LD D, d8 */ + LD_D8(cpu, cpu->d); + break; + case 0x17: /* RLA */ + val = GET_BIT(cpu->a, 7); + cpu->nf = 0; + cpu->zf = 0; + cpu->hf = 0; + cpu->a = (cpu->a << 1) | cpu->cf; + cpu->cf = val; + break; + case 0x18: /* JR r8 */ + JR_8(cpu); + break; + case 0x19: /* ADD HL, DE */ + ADD_16(cpu, cpu->hl, cpu->de); + break; + case 0x1a: /* LD A, (DE) */ + cpu->a = cpu->mem_read(cpu, cpu->de); + break; + case 0x1b: /* DEC BC */ + cpu->bc--; + break; + case 0x1c: /* INC E */ + INC_8(cpu, cpu->e); + break; + case 0x1d: /* DEC E */ + DEC_8(cpu, cpu->e); + break; + case 0x1e: /* LD E, d8 */ + LD_D8(cpu, cpu->e); + break; + case 0x1f: /* RRA */ + val = GET_BIT(cpu->a, 0); + cpu->nf = 0; + cpu->zf = 0; + cpu->hf = 0; + cpu->a = (cpu->cf << 7) | (cpu->a >> 1) ; + cpu->cf = val; + break; + case 0x20: /* JR NZ, r8 */ + if (!cpu->zf) { + JR_8(cpu); + } else { + cpu->pc++; + } + break; + case 0x21: /* LD HL, d16 */ + LD_D16(cpu, cpu->hl); + break; + case 0x22: /* LD (HL-), A */ + cpu->a = cpu->mem_read(cpu, cpu->hl); + cpu->hl--; + break; + case 0x23: /* INC HL */ + cpu->hl++; + break; + case 0x24: /* INC H */ + INC_8(cpu, cpu->h); + break; + case 0x25: /* DEC H */ + DEC_8(cpu, cpu->h); + break; + case 0x26: /* LD h, d8 */ + LD_D8(cpu, cpu->h); + break; + case 0x27: /* DAA */ + /* TODO: DAA */ + break; + case 0x28: /* JR Z, r8 */ + if (cpu->zf) { + JR_8(cpu); + } else { + cpu->pc++; + } + break; + case 0x29: /* ADD HL, HL */ + ADD_16(cpu, cpu->hl, cpu->hl); + break; + case 0x2a: /* LD A, (HL+) */ + cpu->a = cpu->mem_read(cpu, cpu->hl); + cpu->hl--; + break; + case 0x2b: /* DEC HL */ + cpu->hl--; + break; + case 0x2c: /* INC L */ + INC_8(cpu, cpu->l); + break; + case 0x2d: /* DEC L */ + DEC_8(cpu, cpu->l); + break; + case 0x2e: /* LD l, d8 */ + LD_D8(cpu, cpu->l); + break; + case 0x2f: /* CPL */ + cpu->nf = 1; + cpu->hf = 1; + cpu->a = ~cpu->a; + break; + case 0x30: /* JR NC, r8 */ + if (!cpu->cf) { + JR_8(cpu); + } else { + cpu->pc++; + } + break; + case 0x31: /* LD SP, d16 */ + LD_D16(cpu, cpu->sp); + break; + case 0x32: /* LD (HL-), A */ + cpu->mem_write(cpu, cpu->hl--, cpu->a); + break; + case 0x33: /* INC SP */ + cpu->sp++; + break; + case 0x34: /* INC (HL) */ + val = cpu->mem_read(cpu, cpu->hl); + cpu->nf = 0; + cpu->hf = CALC_H_ADD(val, 1); + val++; + cpu->mem_write(cpu, cpu->hl, val); + cpu->zf = (val == 0); + break; + case 0x35: /* DEC (HL) */ + val = cpu->mem_read(cpu, cpu->hl); + cpu->hf = CALC_H_ADD(val, 1); + cpu->zf = (val == 0); + cpu->nf = 1; + val--; + cpu->mem_write(cpu, cpu->hl, val); + break; + case 0x36: /* LD (HL), d8 */ + val = cpu->mem_read(cpu, cpu->pc++); + cpu->mem_write(cpu, cpu->hl++, val); + break; + case 0x37: /* SCF */ + cpu->nf = 0; + cpu->hf = 0; + cpu->cf = 1; + break; + case 0x38: /* JR C, r8*/ + if (cpu->cf) { + JR_8(cpu); + } else { + cpu->pc++; + } + break; + case 0x39: /* ADD HL,SP */ + ADD_16(cpu, cpu->hl, cpu->sp); + break; + case 0x3a: /* LD A, (HL-) */ + cpu->a = cpu->mem_read(cpu, cpu->hl); + cpu->hl--; + break; + case 0x3b: /* DEC SP */ + cpu->sp--; + break; + case 0x3c: /* INC A */ + INC_8(cpu, cpu->a); + break; + case 0x3d: /* DEC A */ + DEC_8(cpu, cpu->a); + break; + case 0x3e: /* LD A, d8 */ + LD_D8(cpu, cpu->a); + break; + case 0x3f: /* CCF */ + cpu->cf = !cpu->cf; + break; + case 0x40: /* LD B,B */ + break; + case 0x41: /* LD B,C */ + cpu->b = cpu->c; + break; + case 0x42: /* LD B,D */ + cpu->b = cpu->d; + break; + case 0x43: /* LD B,E */ + cpu->b = cpu->e; + break; + case 0x44: /* LD B,H */ + cpu->b = cpu->h; + break; + case 0x45: /* LD B,L */ + cpu->b = cpu->l; + break; + case 0x46: /* LD B,(HL) */ + cpu->b = cpu->mem_read(cpu, cpu->hl); + break; + case 0x47: /* LD B,A */ + cpu->b = cpu->a; + break; + case 0x48: /* LD C,B */ + cpu->c = cpu->b; + break; + case 0x49: /* LD C,C */ + break; + case 0x4a: /* LD C,D */ + cpu->c = cpu->d; + break; + case 0x4b: /* LD C,E */ + cpu->c = cpu->e; + break; + case 0x4c: /* LD C,H */ + cpu->c = cpu->h; + break; + case 0x4d: /* LD C,L */ + cpu->c = cpu->l; + break; + case 0x4e: /* LD C,(HL) */ + cpu->c = cpu->mem_read(cpu, cpu->hl); + break; + case 0x4f: /* LD C,A */ + cpu->c = cpu->a; + break; + case 0x50: /* LD D,B */ + cpu->d = cpu->b; + break; + case 0x51: /* LD D,C */ + cpu->d = cpu->c; + break; + case 0x52: /* LD D,D */ + break; + case 0x53: /* LD D,E */ + cpu->d = cpu->e; + break; + case 0x54: /* LD D,H */ + cpu->d = cpu->h; + break; + case 0x55: /* LD D,L */ + cpu->d = cpu->l; + break; + case 0x56: /* LD D,(HL) */ + cpu->d = cpu->mem_read(cpu, cpu->hl); + break; + case 0x57: /* LD D,A */ + cpu->d = cpu->a; + break; + case 0x58: /* LD E,B */ + cpu->e = cpu->b; + break; + case 0x59: /* LD E,C */ + cpu->e = cpu->c; + break; + case 0x5a: /* LD E,D */ + cpu->e = cpu->d; + break; + case 0x5b: /* LD E,E */ + break; + case 0x5c: /* LD E,H */ + cpu->e = cpu->h; + break; + case 0x5d: /* LD E,L */ + cpu->e = cpu->h; + break; + case 0x5e: /* LD E,(HL) */ + cpu->e = cpu->mem_read(cpu, cpu->hl); + break; + case 0x5f: /* LD E,A */ + cpu->e = cpu->a; + break; + case 0x60: /* LD H,B */ + cpu->h = cpu->b; + break; + case 0x61: /* LD H,C */ + cpu->h = cpu->c; + break; + case 0x62: /* LD H,D */ + cpu->h = cpu->d; + break; + case 0x63: /* LD H,E */ + cpu->h = cpu->e; + break; + case 0x64: /* LD H,H */ + break; + case 0x65: /* LD H,L */ + cpu->h = cpu->l; + break; + case 0x66: /* LD H,(HL) */ + cpu->h = cpu->mem_read(cpu, cpu->hl); + break; + case 0x67: /* LD H,A */ + cpu->h = cpu->a; + break; + case 0x68: /* LD L,B */ + cpu->l = cpu->b; + break; + case 0x69: /* LD L,C */ + cpu->l = cpu->c; + break; + case 0x6a: /* LD L,D */ + cpu->l = cpu->d; + break; + case 0x6b: /* LD L,E */ + cpu->l = cpu->e; + break; + case 0x6c: /* LD L,H */ + cpu->l = cpu->h; + break; + case 0x6d: /* LD L,L */ + break; + case 0x6e: /* LD L,(HL) */ + cpu->l = cpu->mem_read(cpu, cpu->hl); + break; + case 0x6f: /* LD L,A */ + cpu->l = cpu->a; + break; + case 0x70: /* LD (HL),B */ + cpu->mem_write(cpu, cpu->hl, cpu->b); + break; + case 0x71: /* LD (HL),C */ + cpu->mem_write(cpu, cpu->hl, cpu->c); + break; + case 0x72: /* LD (HL),D */ + cpu->mem_write(cpu, cpu->hl, cpu->d); + break; + case 0x73: /* LD (HL),E */ + cpu->mem_write(cpu, cpu->hl, cpu->e); + break; + case 0x74: /* LD (HL),H */ + cpu->mem_write(cpu, cpu->hl, cpu->h); + break; + case 0x75: /* LD (HL),L */ + cpu->mem_write(cpu, cpu->hl, cpu->l); + break; + case 0x76: /* HALT */ cpu->halted = 1; - } - -} - -static void ld_into_deref(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg; - uint16_t addr; - - switch (instr) { - case 0x02: reg = LR35902_REG_BC; break; - case 0x12: reg = LR35902_REG_DE; break; - case 0x77: reg = LR35902_REG_HL; break; - default: - ASSERT(0); - return; - } - - addr = lr35902_get_reg_16(cpu, reg); - cpu->mem_write(cpu, addr, cpu->a); -} - -static void ld_d8(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = (instr >> 3) & 0x7; - ++cpu->pc; - _set_reg_8(cpu, reg, cpu->mem_read(cpu, cpu->pc)); -} - -static void ld_d16(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg; - uint16_t val; - - switch(instr) { - case 0x01: reg = LR35902_REG_BC; break; - case 0x11: reg = LR35902_REG_DE; break; - case 0x21: reg = LR35902_REG_HL; break; - case 0x31: reg = LR35902_REG_SP; break; - default: cpu->halted=1; return; - } - - val = cpu->mem_read(cpu, ++cpu->pc); - val |= cpu->mem_read(cpu, ++cpu->pc) << 8; - - lr35902_set_reg_16(cpu, reg, val); -} - -static void ld_a16(struct lr35902_state *cpu, uint8_t instr) -{ - uint16_t a = 0; - _incr_pc(cpu); - a = cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)); - _incr_pc(cpu); - a |= cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)) << 8; - - if(instr == 0xEA) { - /* Store */ - uint16_t val = lr35902_get_reg_8(cpu, LR35902_REG_A); - cpu->mem_write(cpu, a, val); - } else { - /* Load */ - lr35902_set_reg_8(cpu, LR35902_REG_A, cpu->mem_read(cpu, a)); - } - -} - -static void ld_c_offset(struct lr35902_state *cpu, uint8_t instr) -{ - uint16_t addr = 0; - - addr = cpu->c; - addr |= 0xff00; - - switch (instr) { - case 0xf2: - //LD A, ($FF00 + C) - cpu->a = cpu->mem_read(cpu, addr); + break; + case 0x77: /* LD (HL),A */ + cpu->mem_write(cpu, cpu->hl, cpu->a); + break; + case 0x78: /* LD A,B */ + cpu->a = cpu->b; + break; + case 0x79: /* LD A,C */ + cpu->a = cpu->c; + break; + case 0x7a: /* LD A,D */ + cpu->a = cpu->d; + break; + case 0x7b: /* LD A,E */ + cpu->a = cpu->e; + break; + case 0x7c: /* LD A,H */ + cpu->a = cpu->h; + break; + case 0x7d: /* LD A,L */ + cpu->a = cpu->l; + break; + case 0x7e: /* LD A,(HL) */ + cpu->a = cpu->mem_read(cpu, cpu->hl);; + break; + case 0x7f: /* LD A,A */ + break; + case 0x80: /* ADD A,B */ + ADD_8(cpu, cpu->a, cpu->b); + break; + case 0x81: /* ADD A,C */ + ADD_8(cpu, cpu->a, cpu->c); + break; + case 0x82:/* ADD A,D */ + ADD_8(cpu, cpu->a, cpu->d); + break; + case 0x83:/* ADD A,E */ + ADD_8(cpu, cpu->a, cpu->e); + break; + case 0x84:/* ADD A,H */ + ADD_8(cpu, cpu->a, cpu->h); + break; + case 0x85:/* ADD A,B */ + ADD_8(cpu, cpu->a, cpu->l); + break; + case 0x86: /* ADD A,(HL) */ + ADD_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0x87: /* ADD A,A */ + ADD_8(cpu, cpu->a, cpu->a); + break; + case 0x88: /* ADC A,B */ + ADC_8(cpu, cpu->a, cpu->a); + break; + case 0x89: /* ADC A,C */ + ADC_8(cpu, cpu->a, cpu->c); + break; + case 0x8a:/* ADC A,D */ + ADC_8(cpu, cpu->a, cpu->d); + break; + case 0x8b:/* ADC A,E */ + ADC_8(cpu, cpu->a, cpu->e); + break; + case 0x8c:/* ADC A,H */ + ADC_8(cpu, cpu->a, cpu->h); + break; + case 0x8d:/* ADC A,L */ + ADC_8(cpu, cpu->a, cpu->l); + break; + case 0x8e: /* ADC A,(HL) */ + ADC_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0x8f: /* ADC A,A */ + ADC_8(cpu, cpu->a, cpu->a); + break; + case 0x90: /* SUB A,B */ + SUB_8(cpu, cpu->a, cpu->b); + break; + case 0x91: /* SUB A,C */ + SUB_8(cpu, cpu->a, cpu->c); + break; + case 0x92: /* SUB A,D */ + SUB_8(cpu, cpu->a, cpu->d); + break; + case 0x93: /* SUB A,E */ + SUB_8(cpu, cpu->a, cpu->e); + break; + case 0x94: /* SUB A,H */ + SUB_8(cpu, cpu->a, cpu->h); + break; + case 0x95: /* SUB A,L */ + SUB_8(cpu, cpu->a, cpu->l); + break; + case 0x96: /* SUB A,(HL) */ + SUB_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0x97: /* SUB A,A */ + SUB_8(cpu, cpu->a, cpu->a); + break; + case 0x98: /* SBC A, B */ + SBC_8(cpu, cpu->a, cpu->b); + break; + case 0x99: /* SBC A, C */ + SBC_8(cpu, cpu->a, cpu->c); + break; + case 0x9a: /* SBC A, D */ + SBC_8(cpu, cpu->a, cpu->d); + break; + case 0x9b: /* SBC A, E */ + SBC_8(cpu, cpu->a, cpu->e); + break; + case 0x9c: /* SBC A, H */ + SBC_8(cpu, cpu->a, cpu->h); + break; + case 0x9d: /* SBC A, L */ + SBC_8(cpu, cpu->a, cpu->l); + break; + case 0x9e: /* SBC A, (HL) */ + SBC_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0x9f: /* SBC A, A */ + SBC_8(cpu, cpu->a, cpu->a); + break; + case 0xa0: /* AND A, B */ + AND_8(cpu, cpu->a, cpu->b); + break; + case 0xa1: /* AND A, C */ + AND_8(cpu, cpu->a, cpu->c); + break; + case 0xa2: /* AND A, D */ + AND_8(cpu, cpu->a, cpu->d); + break; + case 0xa3: /* AND A, E */ + AND_8(cpu, cpu->a, cpu->e); + break; + case 0xa4: /* AND A, H */ + AND_8(cpu, cpu->a, cpu->h); + break; + case 0xa5: /* AND A, L */ + AND_8(cpu, cpu->a, cpu->l); + break; + case 0xa6: /* AND A, (HL) */ + AND_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0xa7: /* AND A, A */ + AND_8(cpu, cpu->a, cpu->a); + break; + case 0xa8: /* XOR A, B */ + XOR_8(cpu, cpu->a, cpu->b); + break; + case 0xa9: /* XOR A, C */ + XOR_8(cpu, cpu->a, cpu->c); + break; + case 0xaa: /* XOR A, D */ + XOR_8(cpu, cpu->a, cpu->d); + break; + case 0xab: /* XOR A, E */ + XOR_8(cpu, cpu->a, cpu->e); + break; + case 0xac: /* XOR A, H */ + XOR_8(cpu, cpu->a, cpu->h); + break; + case 0xad: /* XOR A, L */ + XOR_8(cpu, cpu->a, cpu->l); + break; + case 0xae: /* XOR A, (HL) */ + XOR_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0xaf: /* XOR A, A */ + XOR_8(cpu, cpu->a, cpu->a); + break; + case 0xb0: /* OR A, B */ + OR_8(cpu, cpu->a, cpu->b); + break; + case 0xb1: /* OR A, C */ + OR_8(cpu, cpu->a, cpu->c); + break; + case 0xb2: /* OR A, D */ + OR_8(cpu, cpu->a, cpu->d); + break; + case 0xb3: /* OR A, E */ + OR_8(cpu, cpu->a, cpu->e); + break; + case 0xb4: /* OR A, H */ + OR_8(cpu, cpu->a, cpu->h); + break; + case 0xb5: /* OR A, L */ + OR_8(cpu, cpu->a, cpu->l); + break; + case 0xb6: /* OR A, (HL) */ + OR_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0xb7: /* OR A, A */ + OR_8(cpu, cpu->a, cpu->a); + break; + case 0xb8: /* CP A, B */ + CP_8(cpu, cpu->a, cpu->b); + break; + case 0xb9: /* CP A, C */ + CP_8(cpu, cpu->a, cpu->c); + break; + case 0xba: /* CP A, D */ + CP_8(cpu, cpu->a, cpu->d); + break; + case 0xbb: /* CP A, E */ + CP_8(cpu, cpu->a, cpu->e); + break; + case 0xbc: /* CP A, H */ + CP_8(cpu, cpu->a, cpu->h); + break; + case 0xbd: /* CP A, L */ + CP_8(cpu, cpu->a, cpu->l); + break; + case 0xbe: /* CP A, (HL) */ + CP_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + break; + case 0xbf: /* CP A, A */ + CP_8(cpu, cpu->a, cpu->a); + break; + case 0xc0: /* RET NZ */ + if (!cpu->zf) { + RET(cpu); + } + break; + case 0xc1: /* POP BC */ + POP_16(cpu, cpu->bc); + break; + case 0xc2: + case 0xc3: /* JP a16 */ + val_16 = cpu->mem_read(cpu, cpu->pc++); + val_16 |= ((uint16_t) cpu->mem_read(cpu, cpu->pc++) << 8); + cpu->pc = val_16; + break; + case 0xc4: /* CALL NZ */ + if (!cpu->zf) { + CALL(cpu); + } else { + cpu->pc += 2; + } + break; + case 0xc5: + case 0xc6: + case 0xc7: /* RST 00 */ + RST(cpu, 0); + break; + case 0xc8: /* RET Z */ + if (cpu->zf) { + RET(cpu); + } + break; + case 0xc9: /* RET */ + RET(cpu); + break; + case 0xca: + case 0xcb: + inst = cpu->mem_read(cpu, cpu->pc++); + cycles = cb_op_cycles[inst]; + switch (inst) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6a: + case 0x6b: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7a: + case 0x7b: + case 0x7c: + case 0x7d: + case 0x7e: + case 0x7f: + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + case 0x8c: + case 0x8d: + case 0x8e: + case 0x8f: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: + case 0x9c: + case 0x9d: + case 0x9e: + case 0x9f: + case 0xa0: + case 0xa1: + case 0xa2: + case 0xa3: + case 0xa4: + case 0xa5: + case 0xa6: + case 0xa7: + case 0xa8: + case 0xa9: + case 0xaa: + case 0xab: + case 0xac: + case 0xad: + case 0xae: + case 0xaf: + case 0xb0: + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb4: + case 0xb5: + case 0xb6: + case 0xb7: + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcc: + case 0xcd: + case 0xce: + case 0xcf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + case 0xe0: + case 0xe1: + case 0xe2: + case 0xe3: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: + case 0xe8: + case 0xe9: + case 0xea: + case 0xeb: + case 0xec: + case 0xed: + case 0xee: + case 0xef: + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + case 0xf8: + case 0xf9: + case 0xfa: + case 0xfb: + case 0xfc: + case 0xfd: + case 0xfe: + case 0xff: + default: + assert(0); + } + break; + case 0xcc: /* CALL Z */ + if (cpu->zf) { + CALL(cpu); + } else { + cpu->pc += 2; + } + break; + case 0xcd: /* CALL */ + CALL(cpu); + break; + case 0xce: + case 0xcf: /* RST 08 */ + RST(cpu, 0x08); + break; + case 0xd0: /* RET NC */ + if (!cpu->cf) { + RET(cpu); + } + break; + case 0xd1: /* POP DE */ + POP_16(cpu, cpu->de); + break; + case 0xd2: + case 0xd3: /* UNDEF */ + break; + case 0xd4: /* CALL NC */ + if (!cpu->nf) { + CALL(cpu); + } else { + cpu->pc += 2; + } + break; + case 0xd5: + case 0xd6: + case 0xd7: /* RST 0x10 */ + RST(cpu, 0x10); + break; + case 0xd8: /* RET C */ + if (cpu->cf) { + RET(cpu); + } + break; + case 0xd9: /* RETI */ + RET(cpu); + cpu->int_state = LR35902_INT_ON; + break; + case 0xda: + case 0xdb: /* UNDEF */ + break; + case 0xdc: /* CALL C */ + if (cpu->cf) { + CALL(cpu); + } else { + cpu->pc += 2; + } + break; + case 0xdd: /* UNDEF */ + break; + case 0xde: + case 0xdf: /* RST 0x18 */ + RST(cpu, 0x18); + break; + case 0xe0: + case 0xe1: /* POP HL */ + POP_16(cpu, cpu->hl); break; case 0xe2: - //LD ($FF00 + C), A - cpu->mem_write(cpu, addr, cpu->a); + case 0xe3: /* UNDEF */ + break; + case 0xe4: /* UNDEF */ + break; + case 0xe5: + case 0xe6: + case 0xe7: /* RST 0x20 */ + RST(cpu, 0x20); + break; + case 0xe8: + case 0xe9: + case 0xea: + case 0xeb: /* UNDEF */ + break; + case 0xec: /* UNDEF */ + break; + case 0xed: /* UNDEF */ + break; + case 0xee: + case 0xef: /* RST 0x28 */ + RST(cpu, 0x28); + break; + case 0xf0: + case 0xf1: /* POP AF */ + cpu->a = cpu->mem_read(cpu, cpu->sp++); + val = cpu->mem_read(cpu, cpu->sp++); + cpu->zf = GET_BIT(val, CPU_F_BIT_POS_Z); + cpu->nf = GET_BIT(val, CPU_F_BIT_POS_N); + cpu->hf = GET_BIT(val, CPU_F_BIT_POS_H); + cpu->cf = GET_BIT(val, CPU_F_BIT_POS_C); + break; + case 0xf2: + case 0xf3: + case 0xf4: /* UNDEF */ + break; + case 0xf5: + case 0xf6: + case 0xf7: /* RST 0x30 */ + RST(cpu, 0x30); + break; + case 0xf8: + case 0xf9: + case 0xfa: + case 0xfb: + case 0xfc: /* UNDEF */ + break; + case 0xfd: /* UNDEF */ + break; + case 0xfe: + case 0xff: /* RST 0x38 */ + RST(cpu, 0x38); break; - default: - ASSERT(0); } - -} - -static void ld_hl_d16(struct lr35902_state *cpu, uint8_t inst) -{ - cpu->hl = _pop_stack_16(cpu); -} - -static void inc_16(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg; - uint16_t val; - - switch (instr) { - case 0x03: reg = LR35902_REG_BC; break; - case 0x13: reg = LR35902_REG_DE; break; - case 0x23: reg = LR35902_REG_HL; break; - case 0x33: reg = LR35902_REG_SP; break; - default: - ASSERT(0); - return; - } - - val = lr35902_get_reg_16(cpu, reg); - val++; - lr35902_set_reg_16(cpu, reg, val); - -} - -static void inc(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = (instr >> 3) & 0x7; - uint8_t val = _get_reg_8(cpu, reg); - val++; - _set_reg_8(cpu, reg, val); - -} - -static void dec(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = (instr >> 3) & 0x7; - uint8_t val = _get_reg_8(cpu, reg); - DEBUG_LOG("reg=%d, val=%d", reg, val); - val--; - DEBUG_LOG("val2=%d", val); - _set_reg_8(cpu, reg, val); - DEBUG_LOG("val3=%d", _get_reg_8(cpu, reg)); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val == 0); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_N, 1); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_H, (val == 0xFF)); -} - -static void dec_16(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = (instr & 0xF0) >> 4; - uint16_t val; - - switch (reg) { - case 0: reg = LR35902_REG_BC; break; - case 1: reg = LR35902_REG_DE; break; - case 2: reg = LR35902_REG_HL; break; - case 3: reg = LR35902_REG_SP; break; - default: - printf("reg: %d\n", reg); - ASSERT(0); - } - - val = lr35902_get_reg_16(cpu, reg); - val--; - lr35902_set_reg_16(cpu, reg, val); - -} - - -static void rlca(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = LR35902_REG_A; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val << 1); - new_val |= GET_BIT(val, 7); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, (new_val == 0)); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 7)); -} - -static void rrca(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = LR35902_REG_A; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val >> 1); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, (new_val == 0)); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 7)); -} - -static void rla(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = LR35902_REG_A; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val << 1); - new_val |= GET_BIT(val, 7); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, (new_val == 0)); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 7)); -} - -static void rra(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = LR35902_REG_A; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val >> 1); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, (new_val == 0)); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 7)); -} - - -static void add(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - uint8_t res = val + val_a; - _set_reg_8(cpu, LR35902_REG_A, (uint8_t) res); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, res == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_H, GET_BIT(val_a, 8)); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(res, 4)); -} - -static void add_d8(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void adc(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - uint16_t res = val + val_a + cpu->c; - _set_reg_8(cpu, LR35902_REG_A, (uint8_t) res); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, res == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_H, GET_BIT(val_a, 8)); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(res, 4)); -} - -static void adc_d8(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void sub(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - val_a -= val; - _set_reg_8(cpu, LR35902_REG_A, val_a); - - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val_a == 0); - SET_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); //TODO: No borrow from bit 4 - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); //TODO: No borrow -} - -static void sub_d8(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void sbc(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - val_a -= val + cpu->c; - _set_reg_8(cpu, LR35902_REG_A, val_a); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val_a == 0); - SET_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); //TODO: No borrow from bit 4 - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); //TODO: No borrow -} - -static void sbc_d8(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void and(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - val_a &= val; - _set_reg_8(cpu, LR35902_REG_A, val_a); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - SET_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void and_d8(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val; - _incr_pc(cpu); - val = cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)); - val &= lr35902_get_reg_8(cpu, LR35902_REG_A); - _set_reg_8(cpu, LR35902_REG_A, val); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - SET_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void xor(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - val_a ^= val; - _set_reg_8(cpu, LR35902_REG_A, val_a); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val_a == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void xor_d8(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val; - _incr_pc(cpu); - val = cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)); - val ^= lr35902_get_reg_8(cpu, LR35902_REG_A); - _set_reg_8(cpu, LR35902_REG_A, val); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void or(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - val_a |= val; - _set_reg_8(cpu, LR35902_REG_A, val_a); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val_a == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void or_d8(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val; - _incr_pc(cpu); - val = cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)); - val |= lr35902_get_reg_8(cpu, LR35902_REG_A); - _set_reg_8(cpu, LR35902_REG_A, val); - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void cp(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - uint8_t val = _get_reg_8(cpu, instr & 7); - val_a -= val; - /* Just test, ignore result */ - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val_a == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void cp_d8(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val_a = _get_reg_8(cpu, LR35902_REG_A); - _incr_pc(cpu); - uint16_t pc = lr35902_get_reg_16(cpu, LR35902_REG_PC); - uint8_t val = cpu->mem_read(cpu, pc); - val_a -= val; - - /* Just test, ignore result */ - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, val_a == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void stop(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void jr(struct lr35902_state *cpu, uint8_t instr) -{ - uint16_t pc = lr35902_get_reg_16(cpu, LR35902_REG_PC); - uint8_t off = cpu->mem_read(cpu, pc + 1); - uint16_t off16; - - if (GET_BIT(off, 7)) { - off16 = (uint16_t) 0xFF00 | off; - } else { - off16 = off; - } - - pc += off16; - lr35902_set_reg_16(cpu, LR35902_REG_PC, pc); - _incr_pc(cpu); - -} - -static void jr_cond(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t flag = (instr >> 3) & 3; - uint16_t pc = lr35902_get_reg_16(cpu, LR35902_REG_PC); - uint16_t offset = cpu->mem_read(cpu, pc + 1); - if (GET_BIT(offset, 7)) { - offset |= 0xFF00; /* Sign extend */ - } - - switch(flag) { - case 0: - flag = GET_BIT(cpu->f, LR35902_FLAG_BIT_Z) == 0; break; - case 1: - flag = GET_BIT(cpu->f, LR35902_FLAG_BIT_Z) == 1; break; - case 2: - flag = GET_BIT(cpu->f, LR35902_FLAG_BIT_C) == 0; break; - case 3: - flag = GET_BIT(cpu->f, LR35902_FLAG_BIT_C) == 1; break; - default: - cpu->halted=1; - } - - if(flag) { - pc += offset; - lr35902_set_reg_16(cpu, LR35902_REG_PC, pc); - } - _incr_pc(cpu); -} - -static void daa(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void cpl(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t val = _get_reg_8(cpu, LR35902_REG_A); - val = ~val; - _set_reg_8(cpu, LR35902_REG_A, val); - - SET_BIT(cpu->f, LR35902_FLAG_BIT_N); - SET_BIT(cpu->f, LR35902_FLAG_BIT_H); -} - -static void scf(struct lr35902_state *cpu, uint8_t instr) -{ - SET_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void ccf(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->f ^= 1 << LR35902_FLAG_BIT_C; -} - -static void halt(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted = 1; -} - -static void ret(struct lr35902_state *cpu, uint8_t instr) -{ - uint16_t jmp_addr = _pop_stack_16(cpu); - - lr35902_set_reg_16(cpu, LR35902_REG_PC, jmp_addr - 1); -} - -static void pop(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg; - uint16_t val; - - switch(instr) { - case 0xC1: reg = LR35902_REG_BC; break; - case 0xD1: reg = LR35902_REG_DE; break; - case 0xE1: reg = LR35902_REG_HL; break; - case 0xF1: reg = LR35902_REG_AF; break; - default: - ASSERT(0); - return; - } - - val = _pop_stack_16(cpu); - - lr35902_set_reg_16(cpu, reg, val); -} - -static void jp(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted = 1; -} - -static void jp_d8(struct lr35902_state *cpu, uint8_t instr) -{ - uint16_t pc = lr35902_get_reg_16(cpu, LR35902_REG_PC); - uint8_t jp_low = cpu->mem_read(cpu, pc + 1); - uint8_t jp_hi = cpu->mem_read(cpu, pc + 2); - uint16_t jp_addr = (jp_hi << 8) | jp_low; - - lr35902_set_reg_16(cpu, LR35902_REG_PC, jp_addr - 1); //TODO: This is a hack -} - -static void jp_a16(struct lr35902_state *cpu, uint8_t instr) -{ - uint16_t addr; - uint8_t cond; - - switch (instr) { - case 0xC2: cond = !GET_BIT(cpu->f, LR35902_FLAG_BIT_Z); break; /* JP NZ */ - case 0xD2: cond = !GET_BIT(cpu->f, LR35902_FLAG_BIT_C); break; /* JP NC */ - case 0xCA: cond = GET_BIT(cpu->f, LR35902_FLAG_BIT_Z); break; /* JP Z */ - case 0xDA: cond = GET_BIT(cpu->f, LR35902_FLAG_BIT_C); break; /* JP C */ - case 0xC3: cond = 1; break; /* JP */ - default: - ASSERT(0); - return; - } - - addr = cpu->mem_read(cpu, LR35902_REG_PC); - _incr_pc(cpu); - addr |= cpu->mem_read(cpu, LR35902_REG_PC) << 8; - _incr_pc(cpu); - - if (cond) { - lr35902_set_reg_16(cpu, LR35902_REG_PC, addr - 1); //TODO: This is a hack - } -} - -static void call(struct lr35902_state *cpu, uint8_t instr) -{ - uint16_t jmp_addr; - _push_stack_16(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC) + 3); - _incr_pc(cpu); - jmp_addr = cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)); - _incr_pc(cpu); - jmp_addr |= (cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC))) << 8; - - lr35902_set_reg_16(cpu, LR35902_REG_PC, jmp_addr - 1); -} - -static void push(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = (instr >> 5) & 7; - uint16_t val; - - switch(instr) { - case 0xF5: reg = LR35902_REG_AF; break; - case 0xC5: reg = LR35902_REG_BC; break; - case 0xD5: reg = LR35902_REG_DE; break; - case 0xE5: reg = LR35902_REG_HL; break; - default: - ASSERT(0); - } - - val = lr35902_get_reg_16(cpu, reg); - _push_stack_16(cpu, val); -} - -static void rst(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void cb_prefix(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t cb_instr; - _incr_pc(cpu); - cb_instr = cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)); - lr35902_cb_instrs[cb_instr >> 3](cpu, cb_instr); - -} - -static void undef(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void reti(struct lr35902_state *cpu, uint8_t instr) -{ - cpu->halted=1; -} - -static void ldh(struct lr35902_state *cpu, uint8_t instr) -{ - //TODO: This is the blocking one (0xE0) - uint16_t addr = 0; - _incr_pc(cpu); - addr = cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_PC)); - addr += 0xFF00; - - if(instr == 0xE0) { - /* Store */ - uint16_t val_a = lr35902_get_reg_8(cpu, LR35902_REG_A); - uint8_t val = (uint8_t) val_a & 0xFF; - cpu->mem_write(cpu, addr, val); - } else if (instr == 0xF0) { - /* Load */ - uint8_t val = cpu->mem_read(cpu, addr); - uint16_t val_a = val; - lr35902_set_reg_8(cpu, LR35902_REG_A, val_a); - } else { - cpu->halted = 1; - } - -} - -static void di(struct lr35902_state *cpu, uint8_t instr) -{ - _schedule_event(cpu, _disable_interrupts, 2); -} - -static void ei(struct lr35902_state *cpu, uint8_t instr) -{ - _schedule_event(cpu, _enable_interrupts, 2); -} - - - -/**************************/ -/* CB-prefix instructions */ -/**************************/ -static void rlc(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val << 1); - new_val |= GET_BIT(val, 7); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void rrc(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val >> 1); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 0)); -} - -static void rl(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val << 1); - new_val |= GET_BIT(val, 7); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 7)); -} - -static void rr(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val >> 1); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 0)); -} - -static void sla(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val << 1); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 7)); -} - -static void sra(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val >> 1); - WRITE_BIT(new_val, 7, GET_BIT(val, 7)); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 0)); -} - -static void swap(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val >> 4) | (val << 4); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_C); -} - -static void srl(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = 0; - - new_val = (val >> 1); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, new_val == 0); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_H); - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_C, GET_BIT(val, 0)); -} - -static void bit(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t bit = (instr >> 3) & 7; - uint8_t val = _get_reg_8(cpu, reg); - - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; - - WRITE_BIT(cpu->f, LR35902_FLAG_BIT_Z, !GET_BIT(val, bit)); - CLR_BIT(cpu->f, LR35902_FLAG_BIT_N); - SET_BIT(cpu->f, LR35902_FLAG_BIT_H); -} - -static void res(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t bit = (instr >> 3) & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = val; - - CLR_BIT(new_val, bit); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; -} - -static void set(struct lr35902_state *cpu, uint8_t instr) -{ - uint8_t reg = instr & 7; - uint8_t bit = (instr >> 3) & 7; - uint8_t val = _get_reg_8(cpu, reg); - uint8_t new_val = val; - - SET_BIT(new_val, bit); - _set_reg_8(cpu, reg, new_val); - cpu->stall_cycles = (reg == LR35902_REG_HL_DEREF) ? 4 : 2; + cpu->stall_cycles = cycles - 1; } diff --git a/src/gbemu/cpu.h b/src/gbemu/cpu.h index eeff950..2187349 100644 --- a/src/gbemu/cpu.h +++ b/src/gbemu/cpu.h @@ -10,10 +10,10 @@ #include -#define LR35902_FLAG_BIT_C 4 -#define LR35902_FLAG_BIT_H 5 -#define LR35902_FLAG_BIT_N 6 -#define LR35902_FLAG_BIT_Z 7 +#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 @@ -78,11 +78,20 @@ struct lr35902_state { uint16_t bc, de, hl, af, pc, sp; }; uint8_t regs_8[NUM_LR35902_REGS_8]; + struct { - uint8_t b, c, d, e, h, l, a, f; + uint8_t b, c, d, e, h, l, a, f_dummy; }; }; + /* 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; + uint8_t stall_cycles; uint8_t halted; lr35902_mem_read_fn mem_read;