diff --git a/src/gbemu/cpu.c b/src/gbemu/cpu.c index 3dd9671..0ee60a3 100644 --- a/src/gbemu/cpu.c +++ b/src/gbemu/cpu.c @@ -124,8 +124,6 @@ static const unsigned int op_cycles[256] = { 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 { \ @@ -294,6 +292,16 @@ static const unsigned int cb_op_cycles[256] = { 0 }; (cpu)->hf = 1; \ } while (0) +#define RES(reg, bit) \ + do { \ + CLR_BIT(reg, bit); \ + } while (0) + +#define SET(reg, bit) \ + do { \ + SET_BIT(reg, bit); \ + } while (0) + #define RL(cpu, reg) \ do { \ uint8_t ci = (cpu)->cf; \ @@ -312,6 +320,7 @@ void lr35902_cycle(struct lr35902_state *cpu) unsigned int cycles; uint8_t val; uint16_t val_16; + uint8_t *reg = NULL; cpu->metrics.cycles++; @@ -1131,15 +1140,21 @@ void lr35902_cycle(struct lr35902_state *cpu) case 0x79: case 0x7a: case 0x7b: - assert(0); case 0x7c: - BIT(cpu, cpu->h, 7); - break; case 0x7d: case 0x7e: - assert(0); case 0x7f: - BIT(cpu, cpu->a, 7); + switch (inst & 7) { + case 0: cpu->b; break; + case 1: val = cpu->c; break; + case 2: val = cpu->d; break; + case 3: val = cpu->e; break; + case 4: val = cpu->h; break; + case 5: val = cpu->l; break; + case 7: val = cpu->a; break; + case 6: val = cpu->mem_read(cpu, cpu->hl); + } + BIT(cpu, val, (inst >> 3) & 7); break; case 0x80: case 0x81: @@ -1205,6 +1220,27 @@ void lr35902_cycle(struct lr35902_state *cpu) case 0xbd: case 0xbe: case 0xbf: + switch (inst & 7) { + case 0: reg = &cpu->b; break; + case 1: reg = &cpu->c; break; + case 2: reg = &cpu->d; break; + case 3: reg = &cpu->e; break; + case 4: reg = &cpu->h; break; + case 5: reg = &cpu->l; break; + case 7: reg = &cpu->a; break; + case 6: + val = cpu->mem_read(cpu, cpu->hl); + CLR_BIT(val, (inst >> 3) & 7); + cpu->mem_write(cpu, cpu->hl, val); + } + + if (!reg) + break; + + CLR_BIT(val, (inst >> 3) & 7); + *reg = val; + + break; case 0xc0: case 0xc1: case 0xc2: @@ -1269,6 +1305,27 @@ void lr35902_cycle(struct lr35902_state *cpu) case 0xfd: case 0xfe: case 0xff: + switch (inst & 7) { + case 0: reg = &cpu->b; break; + case 1: reg = &cpu->c; break; + case 2: reg = &cpu->d; break; + case 3: reg = &cpu->e; break; + case 4: reg = &cpu->h; break; + case 5: reg = &cpu->l; break; + case 7: reg = &cpu->a; break; + case 6: + val = cpu->mem_read(cpu, cpu->hl); + CLR_BIT(val, (inst >> 3) & 7); + cpu->mem_write(cpu, cpu->hl, val); + } + + if (!reg) + break; + + SET_BIT(val, (inst >> 3) & 7); + *reg = val; + + break; default: assert(0); }