reenabled gdb-based debugger

This commit is contained in:
Anthony Pesch 2017-05-15 07:37:19 -04:00
parent 32b1f75e37
commit 08b6b5de1d
7 changed files with 182 additions and 91 deletions

View File

@ -172,6 +172,7 @@ set(REDREAM_SOURCES
src/hw/rom/flash.c
src/hw/sh4/sh4.c
src/hw/sh4/sh4_ccn.c
src/hw/sh4/sh4_dbg.c
src/hw/sh4/sh4_dmac.c
src/hw/sh4/sh4_intc.c
src/hw/sh4/sh4_tmu.c

View File

@ -15,8 +15,6 @@
#include "hw/scheduler.h"
#include "hw/sh4/sh4.h"
DEFINE_OPTION_INT(gdb, 0, "Run gdb debug server");
void dc_poll_input(struct dreamcast *dc) {
if (!dc->poll_input) {
return;
@ -198,6 +196,26 @@ struct execute_interface *dc_create_execute_interface(device_run_cb run,
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);
@ -250,7 +268,9 @@ void dc_destroy(struct dreamcast *dc) {
struct dreamcast *dc_create() {
struct dreamcast *dc = calloc(1, sizeof(struct dreamcast));
dc->debugger = OPTION_gdb ? debugger_create(dc) : NULL;
#ifndef NDEBUG
dc->debugger = debugger_create(dc);
#endif
dc->memory = memory_create(dc);
dc->scheduler = scheduler_create(dc);
dc->sh4 = sh4_create(dc);

View File

@ -165,6 +165,14 @@ void *dc_create_device(struct dreamcast *dc, size_t size, const char *name,
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);

View File

@ -540,7 +540,8 @@ static int gdrom_init(struct device *dev) {
}
void gdrom_dma_end(struct gdrom *gd) {
LOG_GDROM("gd_dma_end, %d / %d read from dma buffer", gd->dma_head, gd->dma_size);
LOG_GDROM("gd_dma_end, %d / %d read from dma buffer", gd->dma_head,
gd->dma_size);
if (gd->dma_head < gd->dma_size) {
return;

View File

@ -41,19 +41,6 @@ static void sh4_swap_fpr_bank(struct sh4 *sh4) {
}
}
static void sh4_invalid_instr(void *data, uint32_t addr) {
/*struct sh4 *self = reinterpret_cast<SH4 *>(ctx->sh4);
auto it = self->breakpoints.find(addr);
CHECK_NE(it, self->breakpoints.end());
// force the main loop to break
self->ctx.num_cycles = 0;
// let the debugger know execution has stopped
self->dc->debugger->Trap();*/
}
void sh4_sr_updated(void *data, uint32_t old_sr) {
struct sh4 *sh4 = data;
struct sh4_ctx *ctx = &sh4->ctx;
@ -227,7 +214,7 @@ static int sh4_init(struct device *dev) {
sh4->guest->ctx = &sh4->ctx;
sh4->guest->mem = sh4->memory_if->space->base;
sh4->guest->space = sh4->memory_if->space;
sh4->guest->invalid_instr = &sh4_invalid_instr;
sh4->guest->invalid_instr = &sh4_dbg_invalid_instr;
sh4->guest->sq_prefetch = &sh4_ccn_sq_prefetch;
sh4->guest->sr_updated = &sh4_sr_updated;
sh4->guest->fpscr_updated = &sh4_fpscr_updated;
@ -259,12 +246,16 @@ void sh4_destroy(struct sh4 *sh4) {
dc_destroy_memory_interface(sh4->memory_if);
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,
&sh4_debug_menu);
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);
sh4->memory_if = dc_create_memory_interface(dc, &sh4_data_map);

View File

@ -51,6 +51,9 @@ struct sh4 {
struct sh4_frontend *frontend;
struct x64_backend *backend;
/* dbg */
struct list breakpoints;
/* intc */
enum sh4_interrupt sorted_interrupts[NUM_SH_INTERRUPTS];
uint64_t sort_id[NUM_SH_INTERRUPTS];
@ -76,6 +79,16 @@ uint32_t sh4_ccn_sq_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask);
void sh4_ccn_sq_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
uint32_t data_mask);
int sh4_dbg_num_registers(struct device *dev);
void sh4_dbg_step(struct device *dev);
void sh4_dbg_add_breakpoint(struct device *dev, int type, uint32_t addr);
void sh4_dbg_remove_breakpoint(struct device *dev, int type, uint32_t addr);
void sh4_dbg_read_memory(struct device *dev, uint32_t addr, uint8_t *buffer,
int size);
void sh4_dbg_read_register(struct device *dev, int n, uint64_t *value,
int *size);
void sh4_dbg_invalid_instr(void *data, uint32_t addr);
void sh4_dmac_ddt(struct sh4 *sh, struct sh4_dtr *dtr);
void sh4_intc_update_pending(struct sh4 *sh4);

View File

@ -1,86 +1,143 @@
// static int sh4_dbg_num_registers() {
// return 59;
// }
#include "hw/debugger.h"
#include "hw/sh4/sh4.h"
#include "jit/frontend/sh4/sh4_disasm.h"
#include "jit/frontend/sh4/sh4_fallback.h"
// static void sh4_dbg_step() {
// // invalidate the block for the current pc
// sh4->code_cache->RemoveBlocks(sh4->ctx.pc);
struct breakpoint {
uint32_t addr;
uint16_t instr;
struct list_node it;
};
// // recompile it with only one instruction and run it
// uint32_t guest_addr = sh4->ctx.pc;
// uint8_t *host_addr = space->Translate(guest_addr);
// int flags = GetCompileFlags() | SH4_SINGLE_INSTR;
static struct breakpoint *lookup_breakpoint(struct sh4 *sh4, uint32_t addr) {
list_for_each_entry(bp, &sh4->breakpoints, struct breakpoint, it) {
if (bp->addr == addr) {
return bp;
}
}
return NULL;
}
// code_pointer_t code = sh4->code_cache->CompileCode(guest_addr, host_addr,
// flags);
// sh4->ctx.pc = code();
static void destroy_breakpoint(struct sh4 *sh4, struct breakpoint *bp) {
list_remove(&sh4->breakpoints, &bp->it);
free(bp);
}
// // let the debugger know we've stopped
// dc->debugger->Trap();
// }
static struct breakpoint *create_breakpoint(struct sh4 *sh4, uint32_t addr,
uint16_t instr) {
struct breakpoint *bp = calloc(1, sizeof(struct breakpoint));
bp->addr = addr;
bp->instr = instr;
list_add(&sh4->breakpoints, &bp->it);
return bp;
}
// static void sh4_dbg_add_breakpoint(int type, uint32_t addr) {
// // save off the original instruction
// uint16_t instr = space->R16(addr);
// breakpoints_.insert(std::make_pair(addr, instr));
void sh4_dbg_invalid_instr(void *data, uint32_t addr) {
struct sh4 *sh4 = data;
// // write out an invalid instruction
// space->W16(addr, 0);
/* ensure a breakpoint exists for this address */
struct breakpoint *bp = lookup_breakpoint(sh4, addr);
CHECK_NOTNULL(bp);
// sh4->code_cache->RemoveBlocks(addr);
// }
/* force a break from dispatch */
sh4->ctx.run_cycles = 0;
// static void sh4_dbg_remove_breakpoint(int type, uint32_t addr) {
// // recover the original instruction
// auto it = breakpoints_.find(addr);
// CHECK_NE(it, breakpoints_.end());
// uint16_t instr = it->second;
// breakpoints_.erase(it);
/* let the debugger know execution has stopped */
debugger_trap(sh4->dc->debugger);
}
// // overwrite the invalid instruction with the original
// space->W16(addr, instr);
void sh4_dbg_read_register(struct device *dev, int n, uint64_t *value,
int *size) {
struct sh4 *sh4 = (struct sh4 *)dev;
// sh4->code_cache->RemoveBlocks(addr);
// }
if (n < 16) {
*value = sh4->ctx.r[n];
} else if (n == 16) {
*value = sh4->ctx.pc;
} else if (n == 17) {
*value = sh4->ctx.pr;
} else if (n == 18) {
*value = sh4->ctx.gbr;
} else if (n == 19) {
*value = sh4->ctx.vbr;
} else if (n == 20) {
*value = sh4->ctx.mach;
} else if (n == 21) {
*value = sh4->ctx.macl;
} else if (n == 22) {
*value = sh4->ctx.sr;
} else if (n == 23) {
*value = sh4->ctx.fpul;
} else if (n == 24) {
*value = sh4->ctx.fpscr;
} else if (n < 41) {
*value = sh4->ctx.fr[n - 25];
} else if (n == 41) {
*value = sh4->ctx.ssr;
} else if (n == 42) {
*value = sh4->ctx.spc;
} else if (n < 51) {
uint32_t *b0 = (sh4->ctx.sr & RB_MASK) ? sh4->ctx.ralt : sh4->ctx.r;
*value = b0[n - 43];
} else if (n < 59) {
uint32_t *b1 = (sh4->ctx.sr & RB_MASK) ? sh4->ctx.r : sh4->ctx.ralt;
*value = b1[n - 51];
}
// static void sh4_dbg_read_memory(uint32_t addr, uint8_t *buffer, int size) {
// space->Memcpy(buffer, addr, size);
// }
*size = 4;
}
// void sh4_dbg_read_register(int n, uint64_t *value, int *size) {
// if (n < 16) {
// *value = sh4->ctx.r[n];
// } else if (n == 16) {
// *value = sh4->ctx.pc;
// } else if (n == 17) {
// *value = sh4->ctx.pr;
// } else if (n == 18) {
// *value = sh4->ctx.gbr;
// } else if (n == 19) {
// *value = sh4->ctx.vbr;
// } else if (n == 20) {
// *value = sh4->ctx.mach;
// } else if (n == 21) {
// *value = sh4->ctx.macl;
// } else if (n == 22) {
// *value = sh4->ctx.sr;
// } else if (n == 23) {
// *value = sh4->ctx.fpul;
// } else if (n == 24) {
// *value = sh4->ctx.fpscr;
// } else if (n < 41) {
// *value = sh4->ctx.fr[n - 25];
// } else if (n == 41) {
// *value = sh4->ctx.ssr;
// } else if (n == 42) {
// *value = sh4->ctx.spc;
// } else if (n < 51) {
// uint32_t *b0 = (sh4->ctx.sr & RB) ? sh4->ctx.ralt : sh4->ctx.r;
// *value = b0[n - 43];
// } else if (n < 59) {
// uint32_t *b1 = (sh4->ctx.sr & RB) ? sh4->ctx.r : sh4->ctx.ralt;
// *value = b1[n - 51];
// }
void sh4_dbg_read_memory(struct device *dev, uint32_t addr, uint8_t *buffer,
int size) {
struct sh4 *sh4 = (struct sh4 *)dev;
// *size = 4;
// }
while (size--) {
*(buffer++) = as_read8(sh4->memory_if->space, addr++);
}
}
void sh4_dbg_remove_breakpoint(struct device *dev, int type, uint32_t addr) {
struct sh4 *sh4 = (struct sh4 *)dev;
struct breakpoint *bp = lookup_breakpoint(sh4, addr);
CHECK_NOTNULL(bp);
/* restore the original instruction */
as_write16(sh4->memory_if->space, addr, bp->instr);
/* free code cache to remove block containing the invalid instruction */
jit_free_blocks(sh4->jit);
destroy_breakpoint(sh4, bp);
}
void sh4_dbg_add_breakpoint(struct device *dev, int type, uint32_t addr) {
struct sh4 *sh4 = (struct sh4 *)dev;
uint16_t instr = as_read16(sh4->memory_if->space, addr);
struct breakpoint *bp = create_breakpoint(sh4, addr, instr);
/* write out an invalid instruction */
as_write16(sh4->memory_if->space, addr, 0);
/* free code cache to remove block containing the original instruction */
jit_free_blocks(sh4->jit);
}
void sh4_dbg_step(struct device *dev) {
struct sh4 *sh4 = (struct sh4 *)dev;
/* run the fallback handler for the current pc */
uint16_t data = as_read16(sh4->memory_if->space, sh4->ctx.pc);
union sh4_instr instr = {data};
struct sh4_opdef *def = sh4_get_opdef(data);
sh4_fallback_cb cb = sh4_get_fallback(data);
cb(sh4->guest, sh4->ctx.pc, instr);
/* let the debugger know we've stopped */
debugger_trap(sh4->dc->debugger);
}
int sh4_dbg_num_registers(struct device *dev) {
return 59;
}