gbdb,cpu,video: reduce number of calls to cycle functions

Instead of calling cpu_cycle() and video_cycle() once per emulated
cycle, call cpu_cycle() once per emulated instruction. This should not
have any obvious effects on the emulation (as currently written),
because all of the memory reads and writes are done in the first
"cycle" of the instruction.

This patch results in a substantial performance gain (>100%, if I
recall correctly).
This commit is contained in:
2018-07-02 00:12:07 -07:00
parent 447276d029
commit ea2ea1e293
5 changed files with 17 additions and 19 deletions

View File

@@ -164,8 +164,10 @@ static void init(void)
static void cycle() static void cycle()
{ {
lr35902_cycle(&cpu); int cycles;
gb_video_cycle(&video);
cycles = lr35902_cycle(&cpu);
gb_video_cycle(&video, cycles);
} }
static void show_prompt() static void show_prompt()

View File

@@ -315,23 +315,17 @@ static const unsigned int cb_extra_cycles[256] = { 0 };
(cpu)->zf = (tmp) == 0; \ (cpu)->zf = (tmp) == 0; \
} while (0) } while (0)
void lr35902_cycle(struct lr35902_state *cpu) int lr35902_cycle(struct lr35902_state *cpu)
{ {
uint8_t inst; uint8_t inst;
uint8_t val; uint8_t val;
uint16_t val_16; uint16_t val_16;
uint8_t *reg = NULL; uint8_t *reg = NULL;
int cycles;
cpu->metrics.cycles++;
if (cpu->stall_cycles > 0) {
cpu->stall_cycles--;
return;
}
cpu->metrics.retired_instrs++; cpu->metrics.retired_instrs++;
inst = cpu->mem_read(cpu, cpu->pc++); inst = cpu->mem_read(cpu, cpu->pc++);
cpu->stall_cycles = op_extra_cycles[inst]; cycles = op_extra_cycles[inst];
switch (inst) { switch (inst) {
case 0x00: /* NOP */ case 0x00: /* NOP */
@@ -995,7 +989,7 @@ void lr35902_cycle(struct lr35902_state *cpu)
case 0xca: case 0xca:
case 0xcb: case 0xcb:
inst = cpu->mem_read(cpu, cpu->pc++); inst = cpu->mem_read(cpu, cpu->pc++);
cpu->stall_cycles = cb_extra_cycles[inst]; cycles = cb_extra_cycles[inst];
switch (inst) { switch (inst) {
case 0x00: case 0x00:
case 0x01: case 0x01:
@@ -1475,4 +1469,7 @@ void lr35902_cycle(struct lr35902_state *cpu)
RST(cpu, 0x38); RST(cpu, 0x38);
break; break;
} }
cpu->metrics.cycles += cycles + 1;
return cycles + 1;
} }

View File

@@ -135,6 +135,6 @@ void lr35902_set_reg_8(struct lr35902_state *cpu,
lr35902_regs_8 reg, lr35902_regs_8 reg,
uint8_t val); uint8_t val);
void lr35902_cycle(struct lr35902_state *cpu); int lr35902_cycle(struct lr35902_state *cpu);
#endif #endif

View File

@@ -12,12 +12,11 @@ void gb_video_init(struct gb_video *video)
memset(video, 0, sizeof(*video)); memset(video, 0, sizeof(*video));
} }
void gb_video_cycle(struct gb_video *video) void gb_video_cycle(struct gb_video *video, int cycles)
{ {
if (video->line_counter < CYCLES_PER_LINE - 1) { video->line_counter += cycles;
video->line_counter++; if (video->line_counter >= CYCLES_PER_LINE) {
} else { video->line_counter -= CYCLES_PER_LINE;
video->line_counter = 0;
video->curline += 1; video->curline += 1;
if (video->curline > LCD_Y_MAX) { if (video->curline > LCD_Y_MAX) {
video->curline = 0; video->curline = 0;

View File

@@ -93,7 +93,7 @@ struct gb_video {
}; };
void gb_video_init(struct gb_video *video); void gb_video_init(struct gb_video *video);
void gb_video_cycle(struct gb_video *video); void gb_video_cycle(struct gb_video *video, int cycles);
uint8_t gb_video_mem_read(struct gb_video *video, uint16_t addr); uint8_t gb_video_mem_read(struct gb_video *video, uint16_t addr);
void gb_video_mem_write(struct gb_video *video, uint16_t addr, uint8_t val); void gb_video_mem_write(struct gb_video *video, uint16_t addr, uint8_t val);