From e06ce8fa7177a007d45c5c203d73f14e7451cc83 Mon Sep 17 00:00:00 2001 From: Anthony Pesch Date: Mon, 23 Oct 2017 17:37:51 -0400 Subject: [PATCH] remove cached device references on each device remove device interface create routines --- src/guest/aica/aica.c | 52 ++++++++++-------- src/guest/arm7/arm7.c | 27 +++++---- src/guest/debugger.c | 14 ++--- src/guest/dreamcast.c | 116 +++++++++++---------------------------- src/guest/dreamcast.h | 57 ++++++------------- src/guest/gdrom/gdrom.c | 23 ++++++-- src/guest/holly/holly.c | 45 ++++++++------- src/guest/pvr/pvr.c | 50 ++++++++++++----- src/guest/pvr/ta.c | 64 ++++++++++++--------- src/guest/scheduler.c | 63 +++++++++++---------- src/guest/scheduler.h | 14 ++--- src/guest/sh4/sh4.c | 35 +++++++----- src/guest/sh4/sh4_ccn.c | 4 +- src/guest/sh4/sh4_dbg.c | 14 +++-- src/guest/sh4/sh4_dmac.c | 8 ++- src/guest/sh4/sh4_mem.c | 46 ++++++++++------ src/guest/sh4/sh4_tmu.c | 13 +++-- 17 files changed, 331 insertions(+), 314 deletions(-) diff --git a/src/guest/aica/aica.c b/src/guest/aica/aica.c index 308adeef..48781427 100644 --- a/src/guest/aica/aica.c +++ b/src/guest/aica/aica.c @@ -282,6 +282,7 @@ static uint32_t aica_encode_arm_irq_l(struct aica *aica, uint32_t intr) { } static void aica_update_arm(struct aica *aica) { + struct arm7 *arm7 = aica->dc->arm7; uint32_t enabled_intr = aica->common_data->SCIEB; uint32_t pending_intr = aica->common_data->SCIPD & enabled_intr; @@ -301,18 +302,19 @@ static void aica_update_arm(struct aica *aica) { if (aica->common_data->L) { /* FIQ handler will load L from common data to check interrupt type */ - arm7_raise_interrupt(aica->arm7, ARM7_INT_FIQ); + arm7_raise_interrupt(arm7, ARM7_INT_FIQ); } } static void aica_update_sh(struct aica *aica) { + struct holly *hl = aica->dc->holly; uint32_t enabled_intr = aica->common_data->MCIEB; uint32_t pending_intr = aica->common_data->MCIPD & enabled_intr; if (pending_intr) { - holly_raise_interrupt(aica->holly, HOLLY_INT_G2AICINT); + holly_raise_interrupt(hl, HOLLY_INT_G2AICINT); } else { - holly_clear_interrupt(aica->holly, HOLLY_INT_G2AICINT); + holly_clear_interrupt(hl, HOLLY_INT_G2AICINT); } } @@ -349,6 +351,7 @@ static uint32_t aica_timer_tctl(struct aica *aica, int n) { } static uint32_t aica_timer_tcnt(struct aica *aica, int n) { + struct scheduler *sched = aica->dc->sched; struct timer *timer = aica->timers[n]; if (!timer) { /* if no timer has been created, return the raw value */ @@ -359,12 +362,13 @@ static uint32_t aica_timer_tcnt(struct aica *aica, int n) { /* else, dynamically compute the value based on the timer's remaining time */ int tctl = aica_timer_tctl(aica, n); int64_t freq = AICA_SAMPLE_FREQ >> tctl; - int64_t remaining = scheduler_remaining_time(aica->scheduler, timer); + int64_t remaining = sched_remaining_time(sched, timer); int64_t cycles = NANO_TO_CYCLES(remaining, freq); return (uint32_t)cycles; } static void aica_timer_reschedule(struct aica *aica, int n, uint32_t period) { + struct scheduler *sched = aica->dc->sched; struct timer **timer = &aica->timers[n]; int64_t freq = AICA_SAMPLE_FREQ >> aica_timer_tctl(aica, n); @@ -372,14 +376,13 @@ static void aica_timer_reschedule(struct aica *aica, int n, uint32_t period) { int64_t remaining = CYCLES_TO_NANO(cycles, freq); if (*timer) { - scheduler_cancel_timer(aica->scheduler, *timer); + sched_cancel_timer(sched, *timer); *timer = NULL; } static timer_cb timer_cbs[3] = {&aica_timer_expire_0, &aica_timer_expire_1, &aica_timer_expire_2}; - *timer = - scheduler_start_timer(aica->scheduler, timer_cbs[n], aica, remaining); + *timer = sched_start_timer(sched, timer_cbs[n], aica, remaining); } static uint32_t aica_rtc_reg_read(struct aica *aica, uint32_t addr, @@ -422,9 +425,9 @@ static void aica_rtc_reg_write(struct aica *aica, uint32_t addr, uint32_t data, static void aica_rtc_timer(void *data) { struct aica *aica = data; + struct scheduler *sched = aica->dc->sched; aica->rtc++; - aica->rtc_timer = - scheduler_start_timer(aica->scheduler, &aica_rtc_timer, aica, NS_PER_SEC); + aica->rtc_timer = sched_start_timer(sched, &aica_rtc_timer, aica, NS_PER_SEC); } static float aica_channel_hz(struct aica_channel *ch) { @@ -750,6 +753,7 @@ static uint32_t aica_common_reg_read(struct aica *aica, uint32_t addr, static void aica_common_reg_write(struct aica *aica, uint32_t addr, uint32_t data, uint32_t mask) { + struct arm7 *arm7 = aica->dc->arm7; uint32_t old_data = READ_DATA((uint8_t *)aica->common_data + addr); WRITE_DATA((uint8_t *)aica->common_data + addr); @@ -807,11 +811,11 @@ static void aica_common_reg_write(struct aica *aica, uint32_t addr, if (aica->common_data->ARMRST) { /* suspend arm when reset is pulled low */ aica->arm_resetting = 1; - arm7_suspend(aica->arm7); + arm7_suspend(arm7); } else if (aica->arm_resetting) { /* reset and resume arm when reset is released */ aica->arm_resetting = 0; - arm7_reset(aica->arm7); + arm7_reset(arm7); } } } break; @@ -833,6 +837,7 @@ static void aica_common_reg_write(struct aica *aica, uint32_t addr, static void aica_next_sample(void *data) { struct aica *aica = data; + struct scheduler *sched = aica->dc->sched; aica_generate_frames(aica); aica_raise_interrupt(aica, AICA_INT_SAMPLE); @@ -841,8 +846,8 @@ static void aica_next_sample(void *data) { /* reschedule */ aica->sample_timer = - scheduler_start_timer(aica->scheduler, &aica_next_sample, aica, - HZ_TO_NANO(AICA_SAMPLE_FREQ / AICA_BATCH_SIZE)); + sched_start_timer(sched, &aica_next_sample, aica, + HZ_TO_NANO(AICA_SAMPLE_FREQ / AICA_BATCH_SIZE)); } static void aica_toggle_recording(struct aica *aica) { @@ -865,9 +870,10 @@ static void aica_toggle_recording(struct aica *aica) { static int aica_init(struct device *dev) { struct aica *aica = (struct aica *)dev; - struct dreamcast *dc = aica->dc; + struct memory *mem = aica->dc->mem; + struct scheduler *sched = aica->dc->sched; - aica->aram = mem_aram(dc->mem, 0x0); + aica->aram = mem_aram(mem, 0x0); /* init channels */ { @@ -878,8 +884,8 @@ static int aica_init(struct device *dev) { } aica->common_data = (struct common_data *)(aica->reg + 0x2800); aica->sample_timer = - scheduler_start_timer(aica->scheduler, &aica_next_sample, aica, - HZ_TO_NANO(AICA_SAMPLE_FREQ / AICA_BATCH_SIZE)); + sched_start_timer(sched, &aica_next_sample, aica, + HZ_TO_NANO(AICA_SAMPLE_FREQ / AICA_BATCH_SIZE)); } /* init timers */ @@ -892,8 +898,8 @@ static int aica_init(struct device *dev) { /* init rtc */ { /* increment clock every second */ - aica->rtc_timer = scheduler_start_timer(aica->scheduler, &aica_rtc_timer, - aica, NS_PER_SEC); + aica->rtc_timer = + sched_start_timer(sched, &aica_rtc_timer, aica, NS_PER_SEC); } return 1; @@ -993,10 +999,12 @@ void aica_debug_menu(struct aica *aica) { #endif void aica_destroy(struct aica *aica) { + struct scheduler *sched = aica->dc->sched; + /* shutdown rtc */ { if (aica->rtc_timer) { - scheduler_cancel_timer(aica->scheduler, aica->rtc_timer); + sched_cancel_timer(sched, aica->rtc_timer); } } @@ -1004,7 +1012,7 @@ void aica_destroy(struct aica *aica) { { for (int i = 0; i < 3; i++) { if (aica->timers[i]) { - scheduler_cancel_timer(aica->scheduler, aica->timers[i]); + sched_cancel_timer(sched, aica->timers[i]); } } } @@ -1012,7 +1020,7 @@ void aica_destroy(struct aica *aica) { /* shutdown channels */ { if (aica->sample_timer) { - scheduler_cancel_timer(aica->scheduler, aica->sample_timer); + sched_cancel_timer(sched, aica->sample_timer); } } diff --git a/src/guest/arm7/arm7.c b/src/guest/arm7/arm7.c index 6ea2253f..5f2d742b 100644 --- a/src/guest/arm7/arm7.c +++ b/src/guest/arm7/arm7.c @@ -131,20 +131,24 @@ static void arm7_compile_code(struct arm7 *arm, uint32_t addr) { void arm7_mem_write(struct arm7 *arm, uint32_t addr, uint32_t data, uint32_t mask) { + struct aica *aica = arm->dc->aica; + if (/*addr >= ARM7_AICA_MEM_BEGIN &&*/ addr <= ARM7_AICA_MEM_END) { - aica_mem_write(arm->aica, addr, data, mask); + aica_mem_write(aica, addr, data, mask); } else if (addr >= ARM7_AICA_REG_BEGIN && addr <= ARM7_AICA_REG_END) { - aica_reg_write(arm->aica, addr - ARM7_AICA_REG_BEGIN, data, mask); + aica_reg_write(aica, addr - ARM7_AICA_REG_BEGIN, data, mask); } else { LOG_FATAL("arm7_mem_write addr=0x%08x", addr); } } uint32_t arm7_mem_read(struct arm7 *arm, uint32_t addr, uint32_t mask) { + struct aica *aica = arm->dc->aica; + if (/*addr >= ARM7_AICA_MEM_BEGIN &&*/ addr <= ARM7_AICA_MEM_END) { - return aica_mem_read(arm->aica, addr, mask); + return aica_mem_read(aica, addr, mask); } else if (addr >= ARM7_AICA_REG_BEGIN && addr <= ARM7_AICA_REG_END) { - return aica_reg_read(arm->aica, addr - ARM7_AICA_REG_BEGIN, mask); + return aica_reg_read(aica, addr - ARM7_AICA_REG_BEGIN, mask); } else { LOG_FATAL("arm7_mem_read addr=0x%08x", addr); } @@ -168,11 +172,11 @@ void arm7_reset(struct arm7 *arm) { arm->ctx.r[R13_SVC] = 0x03007fe0; arm->ctx.r[CPSR] = F_MASK | MODE_SYS; - arm->execute_if->running = 1; + arm->runif.running = 1; } void arm7_suspend(struct arm7 *arm) { - arm->execute_if->running = 0; + arm->runif.running = 0; } static void arm7_run(struct device *dev, int64_t ns) { @@ -200,8 +204,8 @@ static struct jit_guest *arm7_guest_create(struct arm7 *arm) { /* memory interface */ guest->ctx = &arm->ctx; - guest->membase = arm7_base(arm->mem); - guest->mem = arm->mem; + guest->membase = arm7_base(arm->dc->mem); + guest->mem = arm->dc->mem; guest->lookup = &arm7_lookup; guest->r8 = &arm7_read8; guest->r16 = &arm7_read16; @@ -265,15 +269,16 @@ void arm7_destroy(struct arm7 *arm) { arm7_guest_destroy(arm->guest); arm->frontend->destroy(arm->frontend); arm->backend->destroy(arm->backend); - - dc_destroy_execute_interface(arm->execute_if); dc_destroy_device((struct device *)arm); } struct arm7 *arm7_create(struct dreamcast *dc) { struct arm7 *arm = dc_create_device(dc, sizeof(struct arm7), "arm", &arm7_init, NULL); - arm->execute_if = dc_create_execute_interface(&arm7_run, 0); + + /* setup run interface */ + arm->runif.enabled = 1; + arm->runif.run = &arm7_run; return arm; } diff --git a/src/guest/debugger.c b/src/guest/debugger.c index 3e55a8ed..527f082a 100644 --- a/src/guest/debugger.c +++ b/src/guest/debugger.c @@ -32,30 +32,30 @@ static void debugger_gdb_server_resume(void *data) { static void debugger_gdb_server_step(void *data) { struct debugger *dbg = data; - dbg->dev->debug_if->step(dbg->dev); + dbg->dev->dbgif.step(dbg->dev); } static void debugger_gdb_server_add_bp(void *data, int type, intmax_t addr) { struct debugger *dbg = data; - dbg->dev->debug_if->add_bp(dbg->dev, type, (uint32_t)addr); + dbg->dev->dbgif.add_bp(dbg->dev, type, (uint32_t)addr); } static void debugger_gdb_server_rem_bp(void *data, int type, intmax_t addr) { struct debugger *dbg = data; - dbg->dev->debug_if->rem_bp(dbg->dev, type, (uint32_t)addr); + dbg->dev->dbgif.rem_bp(dbg->dev, type, (uint32_t)addr); } static void debugger_gdb_server_read_mem(void *data, intmax_t addr, uint8_t *buffer, int size) { struct debugger *dbg = data; - dbg->dev->debug_if->read_mem(dbg->dev, (uint32_t)addr, buffer, size); + dbg->dev->dbgif.read_mem(dbg->dev, (uint32_t)addr, buffer, size); } static void debugger_gdb_server_read_reg(void *data, int n, intmax_t *value, int *size) { struct debugger *dbg = data; uint64_t v = 0; - dbg->dev->debug_if->read_reg(dbg->dev, n, &v, size); + dbg->dev->dbgif.read_reg(dbg->dev, n, &v, size); *value = v; } #endif @@ -64,7 +64,7 @@ int debugger_init(struct debugger *dbg) { #ifdef HAVE_GDBSERVER /* use the first device found with a debug interface */ list_for_each_entry(dev, &dbg->dc->devices, struct device, it) { - if (dev->debug_if) { + if (dev->dbgif.enabled) { dbg->dev = dev; break; } @@ -79,7 +79,7 @@ int debugger_init(struct debugger *dbg) { gdb_target_t target; target.ctx = dbg; target.endian = GDB_LITTLE_ENDIAN; - target.num_regs = dbg->dev->debug_if->num_regs(dbg->dev); + target.num_regs = dbg->dev->dbgif.num_regs(dbg->dev); target.detach = &debugger_gdb_server_detach; target.stop = &debugger_gdb_server_stop; target.resume = &debugger_gdb_server_resume; diff --git a/src/guest/dreamcast.c b/src/guest/dreamcast.c index 4bfb5228..ae9a5bb8 100644 --- a/src/guest/dreamcast.c +++ b/src/guest/dreamcast.c @@ -63,6 +63,35 @@ void dc_push_audio(struct dreamcast *dc, const int16_t *data, int frames) { dc->push_audio(dc->userdata, data, frames); } +void dc_destroy_device(struct device *dev) { + list_remove(&dev->dc->devices, &dev->it); + + free(dev); +} + +struct device *dc_get_device(struct dreamcast *dc, const char *name) { + list_for_each_entry(dev, &dc->devices, struct device, it) { + if (!strcmp(dev->name, name)) { + return dev; + } + } + return NULL; +} + +void *dc_create_device(struct dreamcast *dc, size_t size, const char *name, + device_init_cb init, device_post_init_cb post_init) { + struct device *dev = calloc(1, size); + + dev->dc = dc; + dev->name = name; + dev->init = init; + dev->post_init = post_init; + + list_add(&dc->devices, &dev->it); + + return dev; +} + void dc_input(struct dreamcast *dc, int port, int button, uint16_t value) { maple_handle_input(dc->maple, port, button, value); } @@ -73,7 +102,7 @@ void dc_tick(struct dreamcast *dc, int64_t ns) { } if (dc->running) { - scheduler_tick(dc->scheduler, ns); + sched_tick(dc->sched, ns); } } @@ -157,25 +186,6 @@ int dc_init(struct dreamcast *dc) { return 0; } - /* cache references to other devices */ - list_for_each_entry(dev, &dc->devices, struct device, it) { - dev->debugger = dc->debugger; - dev->mem = dc->mem; - dev->scheduler = dc->scheduler; - dev->bios = dc->bios; - dev->sh4 = dc->sh4; - dev->arm7 = dc->arm7; - dev->aica = dc->aica; - dev->bios = dc->bios; - dev->boot = dc->boot; - dev->flash = dc->flash; - dev->gdrom = dc->gdrom; - dev->holly = dc->holly; - dev->maple = dc->maple; - dev->pvr = dc->pvr; - dev->ta = dc->ta; - } - /* initialize each device */ list_for_each_entry(dev, &dc->devices, struct device, it) { if (dev->init && !dev->init(dev)) { @@ -194,68 +204,6 @@ int dc_init(struct dreamcast *dc) { return 1; } -void dc_destroy_execute_interface(struct execute_interface *execute) { - free(execute); -} - -struct execute_interface *dc_create_execute_interface(device_run_cb run, - int running) { - struct execute_interface *execute = - calloc(1, sizeof(struct execute_interface)); - execute->run = run; - execute->running = running; - return execute; -} - -void dc_destroy_debug_interface(struct debug_interface *dbg) { - free(dbg); -} - -struct debug_interface *dc_create_debug_interface(device_num_regs_cb num_regs, - device_step_cb step, - device_add_bp_cb add_bp, - device_rem_bp_cb rem_bp, - device_read_mem_cb read_mem, - device_read_reg_cb read_reg) { - struct debug_interface *dbg = calloc(1, sizeof(struct debug_interface)); - dbg->num_regs = num_regs; - dbg->step = step; - dbg->add_bp = add_bp; - dbg->rem_bp = rem_bp; - dbg->read_mem = read_mem; - dbg->read_reg = read_reg; - return dbg; -} - -void dc_destroy_device(struct device *dev) { - list_remove(&dev->dc->devices, &dev->it); - - free(dev); -} - -struct device *dc_get_device(struct dreamcast *dc, const char *name) { - list_for_each_entry(dev, &dc->devices, struct device, it) { - if (!strcmp(dev->name, name)) { - return dev; - } - } - return NULL; -} - -void *dc_create_device(struct dreamcast *dc, size_t size, const char *name, - device_init_cb init, device_post_init_cb post_init) { - struct device *dev = calloc(1, size); - - dev->dc = dc; - dev->name = name; - dev->init = init; - dev->post_init = post_init; - - list_add(&dc->devices, &dev->it); - - return dev; -} - void dc_destroy(struct dreamcast *dc) { ta_destroy(dc->ta); pvr_destroy(dc->pvr); @@ -268,7 +216,7 @@ void dc_destroy(struct dreamcast *dc) { arm7_destroy(dc->arm7); sh4_destroy(dc->sh4); bios_destroy(dc->bios); - scheduler_destroy(dc->scheduler); + sched_destroy(dc->sched); mem_destroy(dc->mem); if (dc->debugger) { debugger_destroy(dc->debugger); @@ -284,7 +232,7 @@ struct dreamcast *dc_create() { dc->debugger = debugger_create(dc); #endif dc->mem = mem_create(dc); - dc->scheduler = scheduler_create(dc); + dc->sched = sched_create(dc); dc->bios = bios_create(dc); dc->sh4 = sh4_create(dc); dc->arm7 = arm7_create(dc); diff --git a/src/guest/dreamcast.h b/src/guest/dreamcast.h index 0cbb0a8f..a9a57dc5 100644 --- a/src/guest/dreamcast.h +++ b/src/guest/dreamcast.h @@ -62,7 +62,8 @@ typedef void (*device_rem_bp_cb)(struct device *, int, uint32_t); typedef void (*device_read_mem_cb)(struct device *, uint32_t, uint8_t *, int); typedef void (*device_read_reg_cb)(struct device *, int, uint64_t *, int *); -struct debug_interface { +struct dbgif { + int enabled; device_num_regs_cb num_regs; device_step_cb step; device_add_bp_cb add_bp; @@ -71,12 +72,13 @@ struct debug_interface { device_read_reg_cb read_reg; }; -/* execute interface */ +/* run interface */ typedef void (*device_run_cb)(struct device *, int64_t); -struct execute_interface { - device_run_cb run; +struct runif { + int enabled; int running; + device_run_cb run; }; /* @@ -99,24 +101,8 @@ struct device { device_post_init_cb post_init; /* optional interfaces */ - struct debug_interface *debug_if; - struct execute_interface *execute_if; - - /* cached references to other devices */ - struct debugger *debugger; - struct memory *mem; - struct scheduler *scheduler; - struct bios *bios; - struct sh4 *sh4; - struct arm7 *arm7; - struct aica *aica; - struct boot *boot; - struct flash *flash; - struct gdrom *gdrom; - struct holly *holly; - struct maple *maple; - struct pvr *pvr; - struct ta *ta; + struct dbgif dbgif; + struct runif runif; struct list_node it; }; @@ -137,7 +123,7 @@ struct dreamcast { /* systems */ struct debugger *debugger; struct memory *mem; - struct scheduler *scheduler; + struct scheduler *sched; /* devices */ struct bios *bios; @@ -166,23 +152,6 @@ struct dreamcast { struct dreamcast *dc_create(); void dc_destroy(struct dreamcast *dc); -void *dc_create_device(struct dreamcast *dc, size_t size, const char *name, - device_init_cb init, device_post_init_cb post_init); -struct device *dc_get_device(struct dreamcast *dc, const char *name); -void dc_destroy_device(struct device *dev); - -struct debug_interface *dc_create_debug_interface(device_num_regs_cb num_regs, - device_step_cb step, - device_add_bp_cb add_bp, - device_rem_bp_cb rem_bp, - device_read_mem_cb read_mem, - device_read_reg_cb read_reg); -void dc_destroy_debug_interface(struct debug_interface *dbg); - -struct execute_interface *dc_create_execute_interface(device_run_cb run, - int running); -void dc_destroy_execute_interface(struct execute_interface *execute); - int dc_init(struct dreamcast *dc); int dc_load(struct dreamcast *dc, const char *path); int dc_running(struct dreamcast *dc); @@ -191,7 +160,13 @@ void dc_resume(struct dreamcast *dc); void dc_tick(struct dreamcast *dc, int64_t ns); void dc_input(struct dreamcast *dc, int port, int button, uint16_t value); -/* client functionality */ +/* device registration */ +void *dc_create_device(struct dreamcast *dc, size_t size, const char *name, + device_init_cb init, device_post_init_cb post_init); +struct device *dc_get_device(struct dreamcast *dc, const char *name); +void dc_destroy_device(struct device *dev); + +/* client interface */ void dc_push_audio(struct dreamcast *dc, const int16_t *data, int frames); void dc_push_pixels(struct dreamcast *dc, const uint8_t *data, int w, int h); void dc_start_render(struct dreamcast *dc, struct ta_context *ctx); diff --git a/src/guest/gdrom/gdrom.c b/src/guest/gdrom/gdrom.c index cb3ecb77..e89156d5 100644 --- a/src/guest/gdrom/gdrom.c +++ b/src/guest/gdrom/gdrom.c @@ -101,18 +101,22 @@ static int gdrom_get_fad(uint8_t a, uint8_t b, uint8_t c, int msf) { } static void gdrom_spi_end(struct gdrom *gd) { + struct holly *hl = gd->dc->holly; + gd->ireason.IO = 1; gd->ireason.CoD = 1; gd->status.DRDY = 1; gd->status.BSY = 0; gd->status.DRQ = 0; - holly_raise_interrupt(gd->holly, HOLLY_INT_G1GDINT); + holly_raise_interrupt(hl, HOLLY_INT_G1GDINT); gd->state = STATE_READ_ATA_CMD; } static void gdrom_spi_cdread(struct gdrom *gd) { + struct holly *hl = gd->dc->holly; + if (gd->cdr_dma) { int max_dma_sectors = sizeof(gd->dma_buffer) / DISC_MAX_SECTOR_SIZE; @@ -150,13 +154,15 @@ static void gdrom_spi_cdread(struct gdrom *gd) { gd->status.DRQ = 1; gd->status.BSY = 0; - holly_raise_interrupt(gd->holly, HOLLY_INT_G1GDINT); + holly_raise_interrupt(hl, HOLLY_INT_G1GDINT); gd->state = STATE_WRITE_SPI_DATA; } } static void gdrom_spi_read(struct gdrom *gd, int offset, int size) { + struct holly *hl = gd->dc->holly; + gd->cdr_num_sectors = 0; gd->pio_head = 0; @@ -169,12 +175,14 @@ static void gdrom_spi_read(struct gdrom *gd, int offset, int size) { gd->status.DRQ = 1; gd->status.BSY = 0; - holly_raise_interrupt(gd->holly, HOLLY_INT_G1GDINT); + holly_raise_interrupt(hl, HOLLY_INT_G1GDINT); gd->state = STATE_READ_SPI_DATA; } static void gdrom_spi_write(struct gdrom *gd, void *data, int size) { + struct holly *hl = gd->dc->holly; + gd->cdr_num_sectors = 0; CHECK(size < (int)sizeof(gd->pio_buffer)); @@ -188,16 +196,18 @@ static void gdrom_spi_write(struct gdrom *gd, void *data, int size) { gd->status.DRQ = 1; gd->status.BSY = 0; - holly_raise_interrupt(gd->holly, HOLLY_INT_G1GDINT); + holly_raise_interrupt(hl, HOLLY_INT_G1GDINT); gd->state = STATE_WRITE_SPI_DATA; } static void gdrom_ata_end(struct gdrom *gd) { + struct holly *hl = gd->dc->holly; + gd->status.DRDY = 1; gd->status.BSY = 0; - holly_raise_interrupt(gd->holly, HOLLY_INT_G1GDINT); + holly_raise_interrupt(hl, HOLLY_INT_G1GDINT); gd->state = STATE_READ_ATA_CMD; } @@ -833,9 +843,10 @@ REG_W32(holly_cb, GD_DRVSEL) { REG_R32(holly_cb, GD_STATUS_COMMAND) { struct gdrom *gd = dc->gdrom; + struct holly *hl = dc->holly; uint16_t value = gd->status.full; LOG_GDROM("read GD_STATUS 0x%x", value); - holly_clear_interrupt(gd->holly, HOLLY_INT_G1GDINT); + holly_clear_interrupt(hl, HOLLY_INT_G1GDINT); return value; } diff --git a/src/guest/holly/holly.c b/src/guest/holly/holly.c index 14056fbc..f5005374 100644 --- a/src/guest/holly/holly.c +++ b/src/guest/holly/holly.c @@ -23,11 +23,13 @@ static void holly_ch2_dma_stop(struct holly *hl) { } static void holly_ch2_dma(struct holly *hl) { + struct sh4 *sh4 = hl->dc->sh4; + struct sh4_dtr dtr = {0}; dtr.channel = 2; dtr.dir = SH4_DMA_TO_ADDR; dtr.addr = *hl->SB_C2DSTAT; - sh4_dmac_ddt(hl->sh4, &dtr); + sh4_dmac_ddt(sh4, &dtr); *hl->SB_C2DLEN = 0; *hl->SB_C2DST = 0; @@ -43,8 +45,8 @@ static void holly_gdrom_dma(struct holly *hl) { return; } - struct gdrom *gd = hl->gdrom; - struct sh4 *sh4 = hl->sh4; + struct gdrom *gd = hl->dc->gdrom; + struct sh4 *sh4 = hl->dc->sh4; /* only gdrom -> sh4 supported for now */ CHECK_EQ(*hl->SB_GDDIR, 1); @@ -92,26 +94,27 @@ static void holly_maple_dma(struct holly *hl) { return; } - struct maple *mp = hl->maple; + struct memory *mem = hl->dc->mem; + struct maple *mp = hl->dc->maple; uint32_t addr = *hl->SB_MDSTAR; while (1) { union maple_transfer desc; - desc.full = sh4_read32(hl->mem, addr); + desc.full = sh4_read32(mem, addr); addr += 4; switch (desc.pattern) { case MAPLE_PATTERN_NORMAL: { - uint32_t result_addr = sh4_read32(hl->mem, addr); + uint32_t result_addr = sh4_read32(mem, addr); addr += 4; /* read message */ struct maple_frame frame, res; - frame.header.full = sh4_read32(hl->mem, addr); + frame.header.full = sh4_read32(mem, addr); addr += 4; for (uint32_t i = 0; i < frame.header.num_words; i++) { - frame.params[i] = sh4_read32(hl->mem, addr); + frame.params[i] = sh4_read32(mem, addr); addr += 4; } @@ -120,15 +123,15 @@ static void holly_maple_dma(struct holly *hl) { /* write response */ if (handled) { - sh4_write32(hl->mem, result_addr, res.header.full); + sh4_write32(mem, result_addr, res.header.full); result_addr += 4; for (uint32_t i = 0; i < res.header.num_words; i++) { - sh4_write32(hl->mem, result_addr, res.params[i]); + sh4_write32(mem, result_addr, res.params[i]); result_addr += 4; } } else { - sh4_write32(hl->mem, result_addr, 0xffffffff); + sh4_write32(mem, result_addr, 0xffffffff); } } break; @@ -168,10 +171,12 @@ static void (*g2_timers[4])(void *); #define DEFINE_G2_DMA_TIMER(ch) \ static void holly_g2_dma_timer_channel##ch(void *data) { \ struct holly *hl = data; \ + struct memory *mem = hl->dc->mem; \ + struct scheduler *sched = hl->dc->sched; \ struct holly_g2_dma *dma = &hl->dma[ch]; \ int chunk_size = 0x1000; \ int n = MIN(dma->len, chunk_size); \ - sh4_memcpy(hl->mem, dma->dst, dma->src, n); \ + sh4_memcpy(mem, dma->dst, dma->src, n); \ dma->dst += n; \ dma->src += n; \ dma->len -= n; \ @@ -183,7 +188,7 @@ static void (*g2_timers[4])(void *); } \ /* g2 bus runs at 16-bits x 25mhz, loosely simulate this */ \ int64_t end = CYCLES_TO_NANO(chunk_size / 2, UINT64_C(25000000)); \ - scheduler_start_timer(hl->scheduler, g2_timers[ch], hl, end); \ + sched_start_timer(sched, g2_timers[ch], hl, end); \ } DEFINE_G2_DMA_TIMER(0); @@ -231,15 +236,17 @@ static void holly_g2_dma(struct holly *hl, int ch) { } static void holly_update_interrupts(struct holly *hl) { + struct sh4 *sh4 = hl->dc->sh4; + /* trigger the respective level-encoded interrupt on the sh4 interrupt controller */ { if ((*hl->SB_ISTNRM & *hl->SB_IML6NRM) || (*hl->SB_ISTERR & *hl->SB_IML6ERR) || (*hl->SB_ISTEXT & *hl->SB_IML6EXT)) { - sh4_raise_interrupt(hl->sh4, SH4_INT_IRL_9); + sh4_raise_interrupt(sh4, SH4_INT_IRL_9); } else { - sh4_clear_interrupt(hl->sh4, SH4_INT_IRL_9); + sh4_clear_interrupt(sh4, SH4_INT_IRL_9); } } @@ -247,9 +254,9 @@ static void holly_update_interrupts(struct holly *hl) { if ((*hl->SB_ISTNRM & *hl->SB_IML4NRM) || (*hl->SB_ISTERR & *hl->SB_IML4ERR) || (*hl->SB_ISTEXT & *hl->SB_IML4EXT)) { - sh4_raise_interrupt(hl->sh4, SH4_INT_IRL_11); + sh4_raise_interrupt(sh4, SH4_INT_IRL_11); } else { - sh4_clear_interrupt(hl->sh4, SH4_INT_IRL_11); + sh4_clear_interrupt(sh4, SH4_INT_IRL_11); } } @@ -257,9 +264,9 @@ static void holly_update_interrupts(struct holly *hl) { if ((*hl->SB_ISTNRM & *hl->SB_IML2NRM) || (*hl->SB_ISTERR & *hl->SB_IML2ERR) || (*hl->SB_ISTEXT & *hl->SB_IML2EXT)) { - sh4_raise_interrupt(hl->sh4, SH4_INT_IRL_13); + sh4_raise_interrupt(sh4, SH4_INT_IRL_13); } else { - sh4_clear_interrupt(hl->sh4, SH4_INT_IRL_13); + sh4_clear_interrupt(sh4, SH4_INT_IRL_13); } } } diff --git a/src/guest/pvr/pvr.c b/src/guest/pvr/pvr.c index 95dff910..7398aa89 100644 --- a/src/guest/pvr/pvr.c +++ b/src/guest/pvr/pvr.c @@ -199,6 +199,8 @@ static void pvr_vblank_in(struct pvr *pvr) { static void pvr_next_scanline(void *data) { struct pvr *pvr = data; + struct holly *hl = pvr->dc->holly; + struct scheduler *sched = pvr->dc->sched; uint32_t num_lines = pvr->SPG_LOAD->vcount + 1; pvr->current_line = (pvr->current_line + 1) % num_lines; @@ -207,11 +209,11 @@ static void pvr_next_scanline(void *data) { switch (pvr->SPG_HBLANK_INT->hblank_int_mode) { case 0x0: if (pvr->current_line == pvr->SPG_HBLANK_INT->line_comp_val) { - holly_raise_interrupt(pvr->holly, HOLLY_INT_PCHIINT); + holly_raise_interrupt(hl, HOLLY_INT_PCHIINT); } break; case 0x2: - holly_raise_interrupt(pvr->holly, HOLLY_INT_PCHIINT); + holly_raise_interrupt(hl, HOLLY_INT_PCHIINT); break; default: LOG_FATAL("unsupported hblank interrupt mode"); @@ -220,12 +222,12 @@ static void pvr_next_scanline(void *data) { /* vblank in */ if (pvr->current_line == pvr->SPG_VBLANK_INT->vblank_in_line_number) { - holly_raise_interrupt(pvr->holly, HOLLY_INT_PCVIINT); + holly_raise_interrupt(hl, HOLLY_INT_PCVIINT); } /* vblank out */ if (pvr->current_line == pvr->SPG_VBLANK_INT->vblank_out_line_number) { - holly_raise_interrupt(pvr->holly, HOLLY_INT_PCVOINT); + holly_raise_interrupt(hl, HOLLY_INT_PCVOINT); } int was_vsync = pvr->SPG_STATUS->vsync; @@ -245,11 +247,13 @@ static void pvr_next_scanline(void *data) { } /* reschedule */ - pvr->line_timer = scheduler_start_timer(pvr->scheduler, &pvr_next_scanline, - pvr, HZ_TO_NANO(pvr->line_clock)); + pvr->line_timer = sched_start_timer(sched, &pvr_next_scanline, pvr, + HZ_TO_NANO(pvr->line_clock)); } static void pvr_reconfigure_spg(struct pvr *pvr) { + struct scheduler *sched = pvr->dc->sched; + /* scale pixel clock frequency */ int pixel_clock = 13500000; if (pvr->FB_R_CTRL->vclk_div) { @@ -277,12 +281,12 @@ static void pvr_reconfigure_spg(struct pvr *pvr) { pvr->SPG_VBLANK->vbstart, pvr->SPG_VBLANK->vbend); if (pvr->line_timer) { - scheduler_cancel_timer(pvr->scheduler, pvr->line_timer); + sched_cancel_timer(sched, pvr->line_timer); pvr->line_timer = NULL; } - pvr->line_timer = scheduler_start_timer(pvr->scheduler, &pvr_next_scanline, - pvr, HZ_TO_NANO(pvr->line_clock)); + pvr->line_timer = sched_start_timer(sched, &pvr_next_scanline, pvr, + HZ_TO_NANO(pvr->line_clock)); } static int pvr_init(struct device *dev) { @@ -404,19 +408,24 @@ struct pvr *pvr_create(struct dreamcast *dc) { REG_W32(pvr_cb, SOFTRESET) { struct pvr *pvr = dc->pvr; + struct ta *ta = dc->ta; + if (!(value & 0x1)) { return; } - ta_soft_reset(pvr->ta); + + ta_soft_reset(ta); } REG_W32(pvr_cb, STARTRENDER) { struct pvr *pvr = dc->pvr; + struct ta *ta = dc->ta; + if (!value) { return; } - ta_start_render(pvr->ta); + ta_start_render(ta); pvr_mark_framebuffer(pvr, *pvr->FB_W_SOF1); pvr_mark_framebuffer(pvr, *pvr->FB_W_SOF2); @@ -425,34 +434,47 @@ REG_W32(pvr_cb, STARTRENDER) { REG_W32(pvr_cb, TA_LIST_INIT) { struct pvr *pvr = dc->pvr; + struct ta *ta = dc->ta; + if (!(value & 0x80000000)) { return; } - ta_list_init(pvr->ta); + + ta_list_init(ta); } REG_W32(pvr_cb, TA_LIST_CONT) { struct pvr *pvr = dc->pvr; + struct ta *ta = dc->ta; + if (!(value & 0x80000000)) { return; } - ta_list_cont(pvr->ta); + + ta_list_cont(ta); } REG_W32(pvr_cb, TA_YUV_TEX_BASE) { struct pvr *pvr = dc->pvr; + struct ta *ta = dc->ta; + pvr->TA_YUV_TEX_BASE->full = value; - ta_yuv_init(pvr->ta); + + ta_yuv_init(ta); } REG_W32(pvr_cb, SPG_LOAD) { struct pvr *pvr = dc->pvr; + pvr->SPG_LOAD->full = value; + pvr_reconfigure_spg(pvr); } REG_W32(pvr_cb, FB_R_CTRL) { struct pvr *pvr = dc->pvr; + pvr->FB_R_CTRL->full = value; + pvr_reconfigure_spg(pvr); } diff --git a/src/guest/pvr/ta.c b/src/guest/pvr/ta.c index 7b731450..b4b68b3d 100644 --- a/src/guest/pvr/ta.c +++ b/src/guest/pvr/ta.c @@ -407,6 +407,8 @@ static void ta_init_context(struct ta *ta, struct ta_context *ctx) { static void ta_write_context(struct ta *ta, struct ta_context *ctx, const void *ptr, int size) { + struct holly *hl = ta->dc->holly; + CHECK_LT(ctx->size + size, (int)sizeof(ctx->params)); memcpy(&ctx->params[ctx->size], ptr, size); ctx->size += size; @@ -436,7 +438,7 @@ static void ta_write_context(struct ta *ta, struct ta_context *ctx, /* it's common that a TA_PARAM_END_OF_LIST is sent before a valid list type has been set */ if (ctx->list_type != TA_NUM_LISTS) { - holly_raise_interrupt(ta->holly, list_interrupts[ctx->list_type]); + holly_raise_interrupt(hl, list_interrupts[ctx->list_type]); } ctx->list_type = TA_NUM_LISTS; ctx->vert_type = TA_NUM_VERTS; @@ -481,12 +483,13 @@ static void ta_write_context(struct ta *ta, struct ta_context *ctx, * level in order to squeeze out extra free performance */ static void ta_save_state(struct ta *ta, struct ta_context *ctx) { - struct pvr *pvr = ta->pvr; + struct memory *mem = ta->dc->mem; + struct pvr *pvr = ta->dc->pvr; /* autosort */ if (pvr->FPU_PARAM_CFG->region_header_type) { /* region array data type 2 */ - uint32_t region_data = sh4_read32(ta->mem, 0x05000000 + *pvr->REGION_BASE); + uint32_t region_data = sh4_read32(mem, 0x05000000 + *pvr->REGION_BASE); ctx->autosort = !(region_data & 0x20000000); } else { /* region array data type 1 */ @@ -516,9 +519,9 @@ static void ta_save_state(struct ta *ta, struct ta_context *ctx) { ((ctx->addr + pvr->ISP_BACKGND_T->tag_address * 4) & 0x7fffff); /* get surface parameters */ - ctx->bg_isp.full = sh4_read32(ta->mem, vram_offset); - ctx->bg_tsp.full = sh4_read32(ta->mem, vram_offset + 4); - ctx->bg_tcw.full = sh4_read32(ta->mem, vram_offset + 8); + ctx->bg_isp.full = sh4_read32(mem, vram_offset); + ctx->bg_tsp.full = sh4_read32(mem, vram_offset + 4); + ctx->bg_tcw.full = sh4_read32(mem, vram_offset + 8); vram_offset += 12; /* get the background depth */ @@ -542,7 +545,7 @@ static void ta_save_state(struct ta *ta, struct ta_context *ctx) { for (int i = 0, bg_offset = 0; i < 3; i++) { CHECK_LE(bg_offset + vertex_size, (int)sizeof(ctx->bg_vertices)); - sh4_memcpy_to_host(ta->mem, &ctx->bg_vertices[bg_offset], vram_offset, + sh4_memcpy_to_host(mem, &ctx->bg_vertices[bg_offset], vram_offset, vertex_size); bg_offset += vertex_size; @@ -553,6 +556,7 @@ static void ta_save_state(struct ta *ta, struct ta_context *ctx) { static void ta_render_context_end(void *data) { struct ta_context *ctx = data; struct ta *ta = ctx->userdata; + struct holly *hl = ta->dc->holly; /* ensure the client has finished rendering */ dc_finish_render(ta->dc); @@ -561,12 +565,14 @@ static void ta_render_context_end(void *data) { ta_free_context(ta, ctx); /* let the game know rendering is complete */ - holly_raise_interrupt(ta->holly, HOLLY_INT_PCEOVINT); - holly_raise_interrupt(ta->holly, HOLLY_INT_PCEOIINT); - holly_raise_interrupt(ta->holly, HOLLY_INT_PCEOTINT); + holly_raise_interrupt(hl, HOLLY_INT_PCEOVINT); + holly_raise_interrupt(hl, HOLLY_INT_PCEOIINT); + holly_raise_interrupt(hl, HOLLY_INT_PCEOTINT); } static void ta_render_context(struct ta *ta, struct ta_context *ctx) { + struct scheduler *sched = ta->dc->sched; + prof_counter_add(COUNTER_ta_renders, 1); /* remove context from pool */ @@ -583,7 +589,7 @@ static void ta_render_context(struct ta *ta, struct ta_context *ctx) { TODO figure out a heuristic involving the number of polygons rendered */ int64_t end = INT64_C(10000000); ctx->userdata = ta; - scheduler_start_timer(ta->scheduler, &ta_render_context_end, ctx, end); + sched_start_timer(sched, &ta_render_context_end, ctx, end); } /* @@ -595,7 +601,7 @@ static void ta_render_context(struct ta *ta, struct ta_context *ctx) { MAX(TA_YUV420_MACROBLOCK_SIZE, TA_YUV422_MACROBLOCK_SIZE) static void ta_yuv_reset(struct ta *ta) { - struct pvr *pvr = ta->pvr; + struct pvr *pvr = ta->dc->pvr; /* FIXME only YUV420 -> YUV422 supported for now */ CHECK_EQ(pvr->TA_YUV_TEX_CTRL->format, 0); @@ -657,7 +663,8 @@ static void ta_yuv_process_block(struct ta *ta, const uint8_t *in_uv, } static void ta_yuv_process_macroblock(struct ta *ta, const void *data) { - struct pvr *pvr = ta->pvr; + struct pvr *pvr = ta->dc->pvr; + struct holly *hl = ta->dc->holly; /* YUV420 data comes in as a series 16x16 macroblocks that need to be converted into a single UYVY422 texture */ @@ -685,7 +692,7 @@ static void ta_yuv_process_macroblock(struct ta *ta, const void *data) { ta_yuv_reset(ta); /* raise DMA end interrupt */ - holly_raise_interrupt(ta->holly, HOLLY_INT_TAYUVINT); + holly_raise_interrupt(hl, HOLLY_INT_TAYUVINT); } } @@ -756,19 +763,19 @@ void ta_init_tables() { */ void ta_texture_write(struct ta *ta, uint32_t dst, const uint8_t *src, int size) { - struct holly *holly = ta->holly; + struct holly *hl = ta->dc->holly; - CHECK(*holly->SB_LMMODE0 == 0); + CHECK(*hl->SB_LMMODE0 == 0); dst &= 0xeeffffff; memcpy(&ta->vram[dst], src, size); } void ta_yuv_write(struct ta *ta, uint32_t dst, const uint8_t *src, int size) { - struct holly *holly = ta->holly; - struct pvr *pvr = ta->pvr; + struct holly *hl = ta->dc->holly; + struct pvr *pvr = ta->dc->pvr; - CHECK(*holly->SB_LMMODE0 == 0); + CHECK(*hl->SB_LMMODE0 == 0); CHECK(size % ta->yuv_macroblock_size == 0); const uint8_t *end = src + size; @@ -779,9 +786,9 @@ void ta_yuv_write(struct ta *ta, uint32_t dst, const uint8_t *src, int size) { } void ta_poly_write(struct ta *ta, uint32_t dst, const uint8_t *src, int size) { - struct holly *holly = ta->holly; + struct holly *hl = ta->dc->holly; - CHECK(*holly->SB_LMMODE0 == 0); + CHECK(*hl->SB_LMMODE0 == 0); CHECK(size % 32 == 0); const uint8_t *end = src + size; @@ -794,11 +801,13 @@ void ta_poly_write(struct ta *ta, uint32_t dst, const uint8_t *src, int size) { void ta_texture_info(struct ta *ta, union tsp tsp, union tcw tcw, const uint8_t **texture, int *texture_size, const uint8_t **palette, int *palette_size) { + struct pvr *pvr = ta->dc->pvr; + uint32_t texture_addr = ta_texture_addr(tsp, tcw, texture_size); *texture = &ta->vram[texture_addr]; uint32_t palette_addr = ta_palette_addr(tcw, palette_size); - uint8_t *palette_ram = (uint8_t *)ta->pvr->PALETTE_RAM000 + palette_addr; + uint8_t *palette_ram = (uint8_t *)pvr->PALETTE_RAM000 + palette_addr; *palette = *palette_size ? palette_ram : NULL; } @@ -807,23 +816,24 @@ void ta_yuv_init(struct ta *ta) { } void ta_list_cont(struct ta *ta) { - struct ta_context *ctx = - ta_get_context(ta, ta->pvr->TA_ISP_BASE->base_address); + struct pvr *pvr = ta->dc->pvr; + struct ta_context *ctx = ta_get_context(ta, pvr->TA_ISP_BASE->base_address); CHECK_NOTNULL(ctx); ta_cont_context(ta, ctx); ta->curr_context = ctx; } void ta_list_init(struct ta *ta) { + struct pvr *pvr = ta->dc->pvr; struct ta_context *ctx = - ta_demand_context(ta, ta->pvr->TA_ISP_BASE->base_address); + ta_demand_context(ta, pvr->TA_ISP_BASE->base_address); ta_init_context(ta, ctx); ta->curr_context = ctx; } void ta_start_render(struct ta *ta) { - struct ta_context *ctx = - ta_get_context(ta, ta->pvr->PARAM_BASE->base_address); + struct pvr *pvr = ta->dc->pvr; + struct ta_context *ctx = ta_get_context(ta, pvr->PARAM_BASE->base_address); CHECK_NOTNULL(ctx); ta_render_context(ta, ctx); } diff --git a/src/guest/scheduler.c b/src/guest/scheduler.c index ccd21509..7e2cdfaf 100644 --- a/src/guest/scheduler.c +++ b/src/guest/scheduler.c @@ -22,36 +22,36 @@ struct scheduler { int64_t base_time; }; -void scheduler_cancel_timer(struct scheduler *sch, struct timer *timer) { +void sched_cancel_timer(struct scheduler *sched, struct timer *timer) { if (!timer->active) { return; } timer->active = 0; - list_remove(&sch->live_timers, &timer->it); - list_add(&sch->free_timers, &timer->it); + list_remove(&sched->live_timers, &timer->it); + list_add(&sched->free_timers, &timer->it); } -int64_t scheduler_remaining_time(struct scheduler *sch, struct timer *timer) { - return timer->expire - sch->base_time; +int64_t sched_remaining_time(struct scheduler *sched, struct timer *timer) { + return timer->expire - sched->base_time; } -struct timer *scheduler_start_timer(struct scheduler *sch, timer_cb cb, - void *data, int64_t ns) { - struct timer *timer = list_first_entry(&sch->free_timers, struct timer, it); +struct timer *sched_start_timer(struct scheduler *sched, timer_cb cb, + void *data, int64_t ns) { + struct timer *timer = list_first_entry(&sched->free_timers, struct timer, it); CHECK_NOTNULL(timer); timer->active = 1; - timer->expire = sch->base_time + ns; + timer->expire = sched->base_time + ns; timer->cb = cb; timer->data = data; /* remove from free list */ - list_remove(&sch->free_timers, &timer->it); + list_remove(&sched->free_timers, &timer->it); /* add to sorted live list */ struct list_node *after = NULL; - list_for_each(&sch->live_timers, it) { + list_for_each(&sched->live_timers, it) { struct timer *entry = list_entry(it, struct timer, it); if (entry->expire > timer->expire) { @@ -61,19 +61,19 @@ struct timer *scheduler_start_timer(struct scheduler *sch, timer_cb cb, after = it; } - list_add_after(&sch->live_timers, after, &timer->it); + list_add_after(&sched->live_timers, after, &timer->it); return timer; } -void scheduler_tick(struct scheduler *sch, int64_t ns) { - int64_t target_time = sch->base_time + ns; +void sched_tick(struct scheduler *sched, int64_t ns) { + int64_t target_time = sched->base_time + ns; - while (sch->dc->running && sch->base_time < target_time) { + while (sched->dc->running && sched->base_time < target_time) { /* run devices up to the next timer */ int64_t next_time = target_time; struct timer *next_timer = - list_first_entry(&sch->live_timers, struct timer, it); + list_first_entry(&sched->live_timers, struct timer, it); if (next_timer && next_timer->expire < next_time) { next_time = next_timer->expire; @@ -81,26 +81,26 @@ void scheduler_tick(struct scheduler *sch, int64_t ns) { /* update base time before running devices and expiring timers in case one of them schedules a new timer */ - int64_t slice = next_time - sch->base_time; - sch->base_time += slice; + int64_t slice = next_time - sched->base_time; + sched->base_time += slice; /* execute each device */ - list_for_each_entry(dev, &sch->dc->devices, struct device, it) { - if (dev->execute_if && dev->execute_if->running) { - dev->execute_if->run(dev, slice); + list_for_each_entry(dev, &sched->dc->devices, struct device, it) { + if (dev->runif.enabled && dev->runif.running) { + dev->runif.run(dev, slice); } } /* execute expired timers */ while (1) { struct timer *timer = - list_first_entry(&sch->live_timers, struct timer, it); + list_first_entry(&sched->live_timers, struct timer, it); - if (!timer || timer->expire > sch->base_time) { + if (!timer || timer->expire > sched->base_time) { break; } - scheduler_cancel_timer(sch, timer); + sched_cancel_timer(sched, timer); /* run the timer */ timer->cb(timer->data); @@ -108,21 +108,20 @@ void scheduler_tick(struct scheduler *sch, int64_t ns) { } } -void scheduler_destroy(struct scheduler *sch) { +void sched_destroy(struct scheduler *sch) { free(sch); } -struct scheduler *scheduler_create(struct dreamcast *dc) { - struct scheduler *sch = calloc(1, sizeof(struct scheduler)); +struct scheduler *sched_create(struct dreamcast *dc) { + struct scheduler *sched = calloc(1, sizeof(struct scheduler)); - sch->dc = dc; + sched->dc = dc; /* add all timers to the free list initially */ for (int i = 0; i < MAX_TIMERS; i++) { - struct timer *timer = &sch->timers[i]; - - list_add(&sch->free_timers, &timer->it); + struct timer *timer = &sched->timers[i]; + list_add(&sched->free_timers, &timer->it); } - return sch; + return sched; } diff --git a/src/guest/scheduler.h b/src/guest/scheduler.h index b25ffe73..3161dd70 100644 --- a/src/guest/scheduler.h +++ b/src/guest/scheduler.h @@ -15,14 +15,14 @@ struct scheduler; typedef void (*timer_cb)(void *); -struct scheduler *scheduler_create(struct dreamcast *dc); -void scheduler_destroy(struct scheduler *sch); +struct scheduler *sched_create(struct dreamcast *dc); +void sched_destroy(struct scheduler *sch); -void scheduler_tick(struct scheduler *sch, int64_t ns); +void sched_tick(struct scheduler *sch, int64_t ns); -struct timer *scheduler_start_timer(struct scheduler *sch, timer_cb cb, - void *data, int64_t ns); -int64_t scheduler_remaining_time(struct scheduler *sch, struct timer *); -void scheduler_cancel_timer(struct scheduler *sch, struct timer *); +struct timer *sched_start_timer(struct scheduler *sch, timer_cb cb, void *data, + int64_t ns); +int64_t sched_remaining_time(struct scheduler *sch, struct timer *); +void sched_cancel_timer(struct scheduler *sch, struct timer *); #endif diff --git a/src/guest/sh4/sh4.c b/src/guest/sh4/sh4.c index 13c52df5..6f89d574 100644 --- a/src/guest/sh4/sh4.c +++ b/src/guest/sh4/sh4.c @@ -118,6 +118,9 @@ static void sh4_compile_code(struct sh4 *sh4, uint32_t addr) { } static void sh4_invalid_instr(struct sh4 *sh4) { + struct memory *mem = sh4->dc->mem; + struct bios *bios = sh4->dc->bios; + /* TODO write tests to confirm if any other instructions generate illegal instruction exceptions */ const uint16_t SH4_INVALID_INSTR = 0xfffd; @@ -125,7 +128,7 @@ static void sh4_invalid_instr(struct sh4 *sh4) { /* let internal systems have a first chance at illegal instructions. note, they will write out invalid instructions other than SH4_INVALID_INSTR in order to trap */ - if (bios_invalid_instr(sh4->bios)) { + if (bios_invalid_instr(bios)) { return; } @@ -134,13 +137,13 @@ static void sh4_invalid_instr(struct sh4 *sh4) { } uint32_t pc = sh4->ctx.pc; - uint16_t data = sh4_read16(sh4->mem, pc); + uint16_t data = sh4_read16(mem, pc); struct jit_opdef *def = sh4_get_opdef(data); enum sh4_exception exc = SH4_EXC_ILLINSTR; /* op may be valid if the delay slot raised this */ if (def->op != SH4_OP_INVALID) { - data = sh4_read16(sh4->mem, pc + 2); + data = sh4_read16(mem, pc + 2); def = sh4_get_opdef(data); exc = SH4_EXC_ILLSLOT; } @@ -179,8 +182,8 @@ static struct jit_guest *sh4_guest_create(struct sh4 *sh4) { /* memory interface */ guest->ctx = &sh4->ctx; - guest->membase = sh4_base(sh4->mem); - guest->mem = sh4->mem; + guest->membase = sh4_base(sh4->dc->mem); + guest->mem = sh4->dc->mem; guest->lookup = &sh4_lookup; guest->r8 = &sh4_read8; guest->r16 = &sh4_read16; @@ -268,7 +271,7 @@ void sh4_reset(struct sh4 *sh4, uint32_t pc) { /* reset interrupts */ sh4_intc_reprioritize(sh4); - sh4->execute_if->running = 1; + sh4->runif.running = 1; } #ifdef HAVE_IMGUI @@ -309,19 +312,25 @@ void sh4_destroy(struct sh4 *sh4) { sh4_guest_destroy(sh4->guest); sh4->frontend->destroy(sh4->frontend); sh4->backend->destroy(sh4->backend); - - dc_destroy_execute_interface(sh4->execute_if); - dc_destroy_debug_interface(sh4->debug_if); dc_destroy_device((struct device *)sh4); } struct sh4 *sh4_create(struct dreamcast *dc) { struct sh4 *sh4 = dc_create_device(dc, sizeof(struct sh4), "sh", &sh4_init, NULL); - sh4->debug_if = dc_create_debug_interface( - &sh4_dbg_num_registers, &sh4_dbg_step, &sh4_dbg_add_breakpoint, - &sh4_dbg_remove_breakpoint, &sh4_dbg_read_memory, &sh4_dbg_read_register); - sh4->execute_if = dc_create_execute_interface(&sh4_run, 0); + + /* setup debug interface */ + sh4->dbgif.enabled = 1; + sh4->dbgif.num_regs = &sh4_dbg_num_registers; + sh4->dbgif.step = &sh4_dbg_step; + sh4->dbgif.add_bp = &sh4_dbg_add_breakpoint; + sh4->dbgif.rem_bp = &sh4_dbg_remove_breakpoint; + sh4->dbgif.read_mem = &sh4_dbg_read_memory; + sh4->dbgif.read_reg = &sh4_dbg_read_register; + + /* setup run interface */ + sh4->runif.enabled = 1; + sh4->runif.run = &sh4_run; return sh4; } diff --git a/src/guest/sh4/sh4_ccn.c b/src/guest/sh4/sh4_ccn.c index 4767ab81..e38155b8 100644 --- a/src/guest/sh4/sh4_ccn.c +++ b/src/guest/sh4/sh4_ccn.c @@ -30,6 +30,8 @@ static void sh4_ccn_reset(struct sh4 *sh4) { } void sh4_ccn_pref(struct sh4 *sh4, uint32_t addr) { + struct memory *mem = sh4->dc->mem; + /* make sure this is a sq related prefetch */ DCHECK(addr >= 0xe0000000 && addr <= 0xe3ffffff); @@ -55,7 +57,7 @@ void sh4_ccn_pref(struct sh4 *sh4, uint32_t addr) { dst |= addr & 0x3ffffe0; } - sh4_memcpy_to_guest(sh4->mem, dst, sh4->ctx.sq[sqi], 32); + sh4_memcpy_to_guest(mem, dst, sh4->ctx.sq[sqi], 32); } uint32_t sh4_ccn_cache_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) { diff --git a/src/guest/sh4/sh4_dbg.c b/src/guest/sh4/sh4_dbg.c index f7b70a14..08f48707 100644 --- a/src/guest/sh4/sh4_dbg.c +++ b/src/guest/sh4/sh4_dbg.c @@ -96,20 +96,22 @@ void sh4_dbg_read_register(struct device *dev, int n, uint64_t *value, void sh4_dbg_read_memory(struct device *dev, uint32_t addr, uint8_t *buffer, int size) { struct sh4 *sh4 = (struct sh4 *)dev; + struct memory *mem = sh4->dc->mem; while (size--) { - *(buffer++) = sh4_read8(sh4->mem, addr++); + *(buffer++) = sh4_read8(mem, addr++); } } void sh4_dbg_remove_breakpoint(struct device *dev, int type, uint32_t addr) { struct sh4 *sh4 = (struct sh4 *)dev; + struct memory *mem = sh4->dc->mem; struct breakpoint *bp = lookup_breakpoint(sh4, addr); CHECK_NOTNULL(bp); /* restore the original instruction */ - sh4_write16(sh4->mem, addr, bp->instr); + sh4_write16(mem, addr, bp->instr); /* free code cache to remove block containing the invalid instruction */ jit_free_code(sh4->jit); @@ -119,12 +121,13 @@ void sh4_dbg_remove_breakpoint(struct device *dev, int type, uint32_t addr) { void sh4_dbg_add_breakpoint(struct device *dev, int type, uint32_t addr) { struct sh4 *sh4 = (struct sh4 *)dev; + struct memory *mem = sh4->dc->mem; - uint16_t instr = sh4_read16(sh4->mem, addr); + uint16_t instr = sh4_read16(mem, addr); struct breakpoint *bp = create_breakpoint(sh4, addr, instr); /* write out an invalid instruction */ - sh4_write16(sh4->mem, addr, 0); + sh4_write16(mem, addr, 0); /* free code cache to remove block containing the original instruction */ jit_free_code(sh4->jit); @@ -132,9 +135,10 @@ void sh4_dbg_add_breakpoint(struct device *dev, int type, uint32_t addr) { void sh4_dbg_step(struct device *dev) { struct sh4 *sh4 = (struct sh4 *)dev; + struct memory *mem = sh4->dc->mem; /* run the fallback handler for the current pc */ - uint16_t data = sh4_read16(sh4->mem, sh4->ctx.pc); + uint16_t data = sh4_read16(mem, sh4->ctx.pc); struct jit_opdef *def = sh4_get_opdef(data); def->fallback((struct jit_guest *)sh4->guest, sh4->ctx.pc, data); diff --git a/src/guest/sh4/sh4_dmac.c b/src/guest/sh4/sh4_dmac.c index 1ef8dbdd..0101c215 100644 --- a/src/guest/sh4/sh4_dmac.c +++ b/src/guest/sh4/sh4_dmac.c @@ -27,15 +27,17 @@ static void sh4_dmac_check(struct sh4 *sh4, int channel) { } void sh4_dmac_ddt(struct sh4 *sh4, struct sh4_dtr *dtr) { + struct memory *mem = sh4->dc->mem; + /* FIXME this should be made asynchronous, at which point the significance of the registers / interrupts should be more obvious */ if (dtr->data) { /* single address mode transfer */ if (dtr->dir == SH4_DMA_FROM_ADDR) { - sh4_memcpy_to_host(sh4->mem, dtr->data, dtr->addr, dtr->size); + sh4_memcpy_to_host(mem, dtr->data, dtr->addr, dtr->size); } else { - sh4_memcpy_to_guest(sh4->mem, dtr->addr, dtr->data, dtr->size); + sh4_memcpy_to_guest(mem, dtr->addr, dtr->data, dtr->size); } } else { /* dual address mode transfer */ @@ -82,7 +84,7 @@ void sh4_dmac_ddt(struct sh4 *sh4, struct sh4_dtr *dtr) { uint32_t src = dtr->dir == SH4_DMA_FROM_ADDR ? dtr->addr : *sar; uint32_t dst = dtr->dir == SH4_DMA_FROM_ADDR ? *dar : dtr->addr; int size = *dmatcr * 32; - sh4_memcpy(sh4->mem, dst, src, size); + sh4_memcpy(mem, dst, src, size); /* update src / addresses as well as remaining count */ *sar = src + size; diff --git a/src/guest/sh4/sh4_mem.c b/src/guest/sh4/sh4_mem.c index ab338658..ec43ca86 100644 --- a/src/guest/sh4/sh4_mem.c +++ b/src/guest/sh4/sh4_mem.c @@ -113,17 +113,19 @@ uint32_t sh4_area7_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) { void sh4_area4_write(struct sh4 *sh4, uint32_t addr, const uint8_t *ptr, int size) { + struct dreamcast *dc = sh4->dc; + addr &= SH4_ADDR_MASK; /* create the two area4 mirrors */ addr &= SH4_AREA4_ADDR_MASK; if (addr >= SH4_TA_POLY_BEGIN && addr <= SH4_TA_POLY_END) { - ta_poly_write(sh4->ta, addr, ptr, size); + ta_poly_write(dc->ta, addr, ptr, size); } else if (addr >= SH4_TA_YUV_BEGIN && addr <= SH4_TA_YUV_END) { - ta_yuv_write(sh4->ta, addr, ptr, size); + ta_yuv_write(dc->ta, addr, ptr, size); } else if (addr >= SH4_TA_TEXTURE_BEGIN && addr <= SH4_TA_TEXTURE_END) { - ta_texture_write(sh4->ta, addr, ptr, size); + ta_texture_write(dc->ta, addr, ptr, size); } else { LOG_FATAL("sh4_area4_write unexpected addr 0x%08x", addr); } @@ -131,30 +133,34 @@ void sh4_area4_write(struct sh4 *sh4, uint32_t addr, const uint8_t *ptr, void sh4_area1_write(struct sh4 *sh4, uint32_t addr, uint32_t data, uint32_t mask) { + struct dreamcast *dc = sh4->dc; + addr &= SH4_ADDR_MASK; /* create the two area1 mirrors */ addr &= SH4_AREA1_ADDR_MASK; if (addr >= SH4_PVR_VRAM64_BEGIN && addr <= SH4_PVR_VRAM64_END) { - pvr_vram64_write(sh4->pvr, addr - SH4_PVR_VRAM64_BEGIN, data, mask); + pvr_vram64_write(dc->pvr, addr - SH4_PVR_VRAM64_BEGIN, data, mask); } else if (addr >= SH4_PVR_VRAM32_BEGIN && addr <= SH4_PVR_VRAM32_END) { - pvr_vram32_write(sh4->pvr, addr - SH4_PVR_VRAM32_BEGIN, data, mask); + pvr_vram32_write(dc->pvr, addr - SH4_PVR_VRAM32_BEGIN, data, mask); } else { LOG_FATAL("sh4_area1_write unexpected addr 0x%08x", addr); } } uint32_t sh4_area1_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) { + struct dreamcast *dc = sh4->dc; + addr &= SH4_ADDR_MASK; /* create the two area1 mirrors */ addr &= SH4_AREA1_ADDR_MASK; if (addr >= SH4_PVR_VRAM64_BEGIN && addr <= SH4_PVR_VRAM64_END) { - return pvr_vram64_read(sh4->pvr, addr - SH4_PVR_VRAM64_BEGIN, mask); + return pvr_vram64_read(dc->pvr, addr - SH4_PVR_VRAM64_BEGIN, mask); } else if (addr >= SH4_PVR_VRAM32_BEGIN && addr <= SH4_PVR_VRAM32_END) { - return pvr_vram32_read(sh4->pvr, addr - SH4_PVR_VRAM32_BEGIN, mask); + return pvr_vram32_read(dc->pvr, addr - SH4_PVR_VRAM32_BEGIN, mask); } else { LOG_FATAL("sh4_area1_read unexpected addr 0x%08x", addr); } @@ -162,26 +168,28 @@ uint32_t sh4_area1_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) { void sh4_area0_write(struct sh4 *sh4, uint32_t addr, uint32_t data, uint32_t mask) { + struct dreamcast *dc = sh4->dc; + /* mask off upper bits creating p0-p4 mirrors */ addr &= SH4_ADDR_MASK; /* flash rom is not accessible in the area0 mirror */ if (addr >= SH4_FLASH_ROM_BEGIN && addr <= SH4_FLASH_ROM_END) { - flash_rom_write(sh4->flash, addr - SH4_FLASH_ROM_BEGIN, data, mask); + flash_rom_write(dc->flash, addr - SH4_FLASH_ROM_BEGIN, data, mask); } else { /* create the two area0 mirrors */ addr &= SH4_AREA0_ADDR_MASK; if (addr >= SH4_HOLLY_REG_BEGIN && addr <= SH4_HOLLY_REG_END) { - holly_reg_write(sh4->holly, addr - SH4_HOLLY_REG_BEGIN, data, mask); + holly_reg_write(dc->holly, addr - SH4_HOLLY_REG_BEGIN, data, mask); } else if (addr >= SH4_PVR_REG_BEGIN && addr <= SH4_PVR_REG_END) { - pvr_reg_write(sh4->pvr, addr - SH4_PVR_REG_BEGIN, data, mask); + pvr_reg_write(dc->pvr, addr - SH4_PVR_REG_BEGIN, data, mask); } else if (addr >= SH4_MODEM_BEGIN && addr <= SH4_MODEM_END) { /* nop */ } else if (addr >= SH4_AICA_REG_BEGIN && addr <= SH4_AICA_REG_END) { - aica_reg_write(sh4->aica, addr - SH4_AICA_REG_BEGIN, data, mask); + aica_reg_write(dc->aica, addr - SH4_AICA_REG_BEGIN, data, mask); } else if (addr >= SH4_AICA_MEM_BEGIN && addr <= SH4_AICA_MEM_END) { - aica_mem_write(sh4->aica, addr - SH4_AICA_MEM_BEGIN, data, mask); + aica_mem_write(dc->aica, addr - SH4_AICA_MEM_BEGIN, data, mask); } else if (addr >= SH4_HOLLY_EXT_BEGIN && addr <= SH4_HOLLY_EXT_END) { /* nop */ } else { @@ -191,29 +199,31 @@ void sh4_area0_write(struct sh4 *sh4, uint32_t addr, uint32_t data, } uint32_t sh4_area0_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) { + struct dreamcast *dc = sh4->dc; + /* mask off upper bits creating p0-p4 mirrors */ addr &= SH4_ADDR_MASK; /* boot / flash rom are not accessible in the area0 mirror */ if (/*addr >= SH4_BOOT_ROM_BEGIN &&*/ addr <= SH4_BOOT_ROM_END) { - return boot_rom_read(sh4->boot, addr - SH4_BOOT_ROM_BEGIN, mask); + return boot_rom_read(dc->boot, addr - SH4_BOOT_ROM_BEGIN, mask); } else if (addr >= SH4_FLASH_ROM_BEGIN && addr <= SH4_FLASH_ROM_END) { - return flash_rom_read(sh4->flash, addr - SH4_FLASH_ROM_BEGIN, mask); + return flash_rom_read(dc->flash, addr - SH4_FLASH_ROM_BEGIN, mask); } /* create the two area0 mirrors */ addr &= SH4_AREA0_ADDR_MASK; if (addr >= SH4_HOLLY_REG_BEGIN && addr <= SH4_HOLLY_REG_END) { - return holly_reg_read(sh4->holly, addr - SH4_HOLLY_REG_BEGIN, mask); + return holly_reg_read(dc->holly, addr - SH4_HOLLY_REG_BEGIN, mask); } else if (addr >= SH4_PVR_REG_BEGIN && addr <= SH4_PVR_REG_END) { - return pvr_reg_read(sh4->pvr, addr - SH4_PVR_REG_BEGIN, mask); + return pvr_reg_read(dc->pvr, addr - SH4_PVR_REG_BEGIN, mask); } else if (addr >= SH4_MODEM_BEGIN && addr <= SH4_MODEM_END) { return 0; } else if (addr >= SH4_AICA_REG_BEGIN && addr <= SH4_AICA_REG_END) { - return aica_reg_read(sh4->aica, addr - SH4_AICA_REG_BEGIN, mask); + return aica_reg_read(dc->aica, addr - SH4_AICA_REG_BEGIN, mask); } else if (addr >= SH4_AICA_MEM_BEGIN && addr <= SH4_AICA_MEM_END) { - return aica_mem_read(sh4->aica, addr - SH4_AICA_MEM_BEGIN, mask); + return aica_mem_read(dc->aica, addr - SH4_AICA_MEM_BEGIN, mask); } else if (addr >= SH4_HOLLY_EXT_BEGIN && addr <= SH4_HOLLY_EXT_END) { return 0; } else { diff --git a/src/guest/sh4/sh4_tmu.c b/src/guest/sh4/sh4_tmu.c index c6d93786..e02f22c6 100644 --- a/src/guest/sh4/sh4_tmu.c +++ b/src/guest/sh4/sh4_tmu.c @@ -15,6 +15,8 @@ static void sh4_tmu_reschedule(struct sh4 *sh4, int n, uint32_t tcnt, uint32_t tcr); static uint32_t sh4_tmu_tcnt(struct sh4 *sh4, int n) { + struct scheduler *sched = sh4->dc->sched; + /* TCNT values aren't updated in real time. if a timer is enabled, query the scheduler to figure out how many cycles are remaining for the given timer */ @@ -28,7 +30,7 @@ static uint32_t sh4_tmu_tcnt(struct sh4 *sh4, int n) { this to change */ uint32_t tcr = *TCR(n); int64_t freq = PERIPHERAL_CLOCK_FREQ >> PERIPHERAL_SCALE[tcr & 7]; - int64_t remaining = scheduler_remaining_time(sh4->scheduler, timer); + int64_t remaining = sched_remaining_time(sched, timer); int64_t cycles = NANO_TO_CYCLES(remaining, freq); return (uint32_t)cycles; @@ -73,6 +75,7 @@ static void sh4_tmu_expire_2(void *data) { static void sh4_tmu_reschedule(struct sh4 *sh4, int n, uint32_t tcnt, uint32_t tcr) { + struct scheduler *sched = sh4->dc->sched; struct timer **timer = &sh4->tmu_timers[n]; int64_t freq = PERIPHERAL_CLOCK_FREQ >> PERIPHERAL_SCALE[tcr & 7]; @@ -80,16 +83,18 @@ static void sh4_tmu_reschedule(struct sh4 *sh4, int n, uint32_t tcnt, int64_t remaining = CYCLES_TO_NANO(cycles, freq); if (*timer) { - scheduler_cancel_timer(sh4->scheduler, *timer); + sched_cancel_timer(sched, *timer); *timer = NULL; } timer_cb cb = (n == 0 ? &sh4_tmu_expire_0 : n == 1 ? &sh4_tmu_expire_1 : &sh4_tmu_expire_2); - *timer = scheduler_start_timer(sh4->scheduler, cb, sh4, remaining); + *timer = sched_start_timer(sched, cb, sh4, remaining); } static void sh4_tmu_update_tstr(struct sh4 *sh4) { + struct scheduler *sched = sh4->dc->sched; + for (int i = 0; i < 3; i++) { struct timer **timer = &sh4->tmu_timers[i]; @@ -103,7 +108,7 @@ static void sh4_tmu_update_tstr(struct sh4 *sh4) { *TCNT(i) = sh4_tmu_tcnt(sh4, i); /* disable the timer */ - scheduler_cancel_timer(sh4->scheduler, *timer); + sched_cancel_timer(sched, *timer); *timer = NULL; } }