From 6d7979571d08d7b020022fa169a34a29fc20dfdc Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 21 Jul 2013 01:56:45 +0300 Subject: [PATCH] drc: debug improvements --- cpu/drc/emit_arm.c | 15 +++++++ cpu/sh2/compiler.c | 27 +++++++++---- cpu/sh2/mame/sh2pico.c | 24 ++++++++---- cpu/sh2/sh2.c | 88 +++++++++++++++++++++++++++++++++--------- pico/pico.c | 4 ++ pico/pico_int.h | 4 +- 6 files changed, 126 insertions(+), 36 deletions(-) diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index efee0f3..2ac8e32 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -639,6 +639,21 @@ static int emith_xbranch(int cond, void *target, int is_call) EOP_MOV_REG_ASR(d,d,32 - (bits)); \ } +#define emith_do_caller_regs(mask, func) { \ + u32 _reg_mask = (mask) & 0x500f; \ + if (_reg_mask) { \ + if (__builtin_parity(_reg_mask) == 1) \ + _reg_mask |= 0x10; /* eabi align */ \ + func(_reg_mask); \ + } \ +} + +#define emith_save_caller_regs(mask) \ + emith_do_caller_regs(mask, EOP_STMFD_SP) + +#define emith_restore_caller_regs(mask) \ + emith_do_caller_regs(mask, EOP_LDMFD_SP) + // upto 4 args #define emith_pass_arg_r(arg, reg) \ EOP_MOV_REG_SIMPLE(arg, reg) diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index bdf2cea..46acb52 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -572,7 +572,7 @@ static void *dr_prepare_ext_branch(u32 pc, int is_slave, int tcache_id) break; cnt = i + 1; if (cnt >= block_link_pool_max_counts[tcache_id]) { - dbg(1, "bl overflow for tcache %d\n", tcache_id); + dbg(1, "bl overflow for tcache %d", tcache_id); return NULL; } bl += cnt; @@ -994,6 +994,18 @@ static void rcache_unlock_all(void) reg_temp[i].flags &= ~HRF_LOCKED; } +static inline u32 rcache_used_hreg_mask(void) +{ + u32 mask = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(reg_temp); i++) + if (reg_temp[i].type != HR_FREE) + mask |= 1 << reg_temp[i].hreg; + + return mask; +} + static void rcache_clean(void) { int i; @@ -1477,16 +1489,18 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) emit_move_r_imm32(SHR_PC, pc); sr = rcache_get_reg(SHR_SR, RC_GR_RMW); FLUSH_CYCLES(sr); - // rcache_clean(); // FIXME - rcache_flush(); + rcache_clean(); + + tmp = rcache_used_hreg_mask(); + emith_save_caller_regs(tmp); emit_do_static_regs(1, 0); emith_pass_arg_r(0, CONTEXT_REG); emith_call(do_sh2_cmp); + emith_restore_caller_regs(tmp); } #endif pc += 2; - cycles += opd->cycles; if (skip_op > 0) { skip_op--; @@ -2517,6 +2531,8 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) end_op: rcache_unlock_all(); + cycles += opd->cycles; + if (op_flags[i+1] & OF_DELAY_OP) { do_host_disasm(tcache_id); continue; @@ -3083,9 +3099,6 @@ int sh2_drc_init(SH2 *sh2) for (i = 1; i < ARRAY_SIZE(tcache_bases); i++) tcache_bases[i] = tcache_ptrs[i] = tcache_bases[i - 1] + tcache_sizes[i - 1]; - // tmp - PicoOpt |= POPT_DIS_VDP_FIFO; - #if (DRC_DEBUG & 4) for (i = 0; i < ARRAY_SIZE(block_tables); i++) tcache_dsm_ptrs[i] = tcache_bases[i]; diff --git a/cpu/sh2/mame/sh2pico.c b/cpu/sh2/mame/sh2pico.c index 1a70d43..10d16ba 100644 --- a/cpu/sh2/mame/sh2pico.c +++ b/cpu/sh2/mame/sh2pico.c @@ -72,8 +72,13 @@ static unsigned int op_refs[0x10000]; int sh2_execute(SH2 *sh2, int cycles) { #ifdef DRC_CMP - unsigned int base_pc = 0, end_pc = 0; - unsigned char op_flags[BLOCK_INSN_LIMIT]; + static unsigned int base_pc_[2] = { 0, 0 }; + static unsigned int end_pc_[2] = { 0, 0 }; + static unsigned char op_flags_[2][BLOCK_INSN_LIMIT]; + unsigned int *base_pc = &base_pc_[sh2->is_slave]; + unsigned int *end_pc = &end_pc_[sh2->is_slave]; + unsigned char *op_flags = op_flags_[sh2->is_slave]; + unsigned int pc_expect = sh2->pc; #endif UINT32 opcode; @@ -88,20 +93,23 @@ int sh2_execute(SH2 *sh2, int cycles) { #ifdef DRC_CMP if (!sh2->delay) { - if (sh2->pc < base_pc || sh2->pc >= end_pc) { - base_pc = sh2->pc; - scan_block(base_pc, sh2->is_slave, - op_flags, &end_pc, NULL); + if (sh2->pc < *base_pc || sh2->pc >= *end_pc) { + *base_pc = sh2->pc; + scan_block(*base_pc, sh2->is_slave, + op_flags, end_pc, NULL); } - if ((op_flags[(sh2->pc - base_pc) / 2] - & OF_BTARGET) || sh2->pc == base_pc) + if ((op_flags[(sh2->pc - *base_pc) / 2] + & OF_BTARGET) || sh2->pc == *base_pc + || pc_expect != sh2->pc) // branched { + pc_expect = sh2->pc; if (sh2->icount < 0) break; } do_sh2_trace(sh2, sh2->icount); } + pc_expect += 2; #endif if (sh2->delay) diff --git a/cpu/sh2/sh2.c b/cpu/sh2/sh2.c index 1f034cd..fbf0c6d 100644 --- a/cpu/sh2/sh2.c +++ b/cpu/sh2/sh2.c @@ -129,25 +129,50 @@ void sh2_unpack(SH2 *sh2, const unsigned char *buff) #include #include #include +#undef _USE_CZ80 // HACK +#include #include static SH2 sh2ref[2]; -static int current_slave = -1; static unsigned int mem_val; static FILE *f; +enum ctl_byte { + CTL_MASTERSLAVE = 0x80, + CTL_EA = 0x82, + CTL_EAVAL = 0x83, + CTL_M68KPC = 0x84, + CTL_CYCLES = 0x85, +}; + #define SH2MAP_ADDR2OFFS_R(a) \ ((((a) >> 25) & 3) | (((a) >> 27) & 0x1c)) static unsigned int local_read32(SH2 *sh2, u32 a) { const sh2_memmap *sh2_map = sh2->read16_map; + u16 *pd; uptr p; sh2_map += SH2MAP_ADDR2OFFS_R(a); p = sh2_map->addr; if (!map_flag_set(p)) { - u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~3)); + pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1)); + return (pd[0] << 16) | pd[1]; + } + + if ((a & 0xfffff000) == 0xc0000000) { + // data array + pd = (u16 *)Pico32xMem->data_array[sh2->is_slave] + + (a & 0xfff) / 2; + return (pd[0] << 16) | pd[1]; + } + if ((a & 0xdfffffc0) == 0x4000) { + pd = &Pico32x.regs[(a & 0x3f) / 2]; + return (pd[0] << 16) | pd[1]; + } + if ((a & 0xdffffe00) == 0x4200) { + pd = &Pico32xMem->pal[(a & 0x1ff) / 2]; return (pd[0] << 16) | pd[1]; } @@ -162,6 +187,8 @@ static void write_uint(unsigned char ctl, unsigned int v) void do_sh2_trace(SH2 *current, int cycles) { + static int current_slave = -1; + static u32 current_m68k_pc; SH2 *sh2o = &sh2ref[current->is_slave]; u32 *regs_a = (void *)current; u32 *regs_o = (void *)sh2o; @@ -172,9 +199,14 @@ void do_sh2_trace(SH2 *current, int cycles) if (f == NULL) f = fopen("tracelog", "wb"); + if (SekPc != current_m68k_pc) { + current_m68k_pc = SekPc; + write_uint(CTL_M68KPC, current_m68k_pc); + } + if (current->is_slave != current_slave) { current_slave = current->is_slave; - v = 0x80 | current->is_slave; + v = CTL_MASTERSLAVE | current->is_slave; fwrite(&v, 1, 1, f); } @@ -188,15 +220,15 @@ void do_sh2_trace(SH2 *current, int cycles) } if (current->ea != sh2o->ea) { - write_uint(0x82, current->ea); + write_uint(CTL_EA, current->ea); sh2o->ea = current->ea; } val = local_read32(current, current->ea); if (mem_val != val) { - write_uint(0x83, val); + write_uint(CTL_EAVAL, val); mem_val = val; } - write_uint(0x84, cycles); + write_uint(CTL_CYCLES, cycles); } static const char *regnames[] = { @@ -208,6 +240,19 @@ static const char *regnames[] = { "gbr", "vbr", "mach","macl", }; +static void dump_regs(SH2 *sh2) +{ + char csh2; + int i; + + csh2 = sh2->is_slave ? 's' : 'm'; + for (i = 0; i < 16/2; i++) + printf("%csh2 r%d: %08x r%02d: %08x\n", csh2, + i, sh2->r[i], i+8, sh2->r[i+8]); + printf("%csh2 PC: %08x , %08x\n", csh2, sh2->pc, sh2->ppc); + printf("%csh2 SR: %03x PR: %08x\n", csh2, sh2->sr, sh2->pr); +} + void do_sh2_cmp(SH2 *current) { static int current_slave; @@ -221,31 +266,39 @@ void do_sh2_cmp(SH2 *current) int bad = 0; int cycles; int i, ret; - char csh2; - if (f == NULL) + if (f == NULL) { f = fopen("tracelog", "rb"); + sh2ref[1].is_slave = 1; + } while (1) { ret = fread(&code, 1, 1, f); if (ret <= 0) break; - if (code == 0x84) { + if (code == CTL_CYCLES) { fread(&cycles_o, 1, 4, f); break; } switch (code) { - case 0x80: - case 0x81: + case CTL_MASTERSLAVE: + case CTL_MASTERSLAVE + 1: current_slave = code & 1; break; - case 0x82: + case CTL_EA: fread(&sh2o->ea, 4, 1, f); break; - case 0x83: + case CTL_EAVAL: fread(¤t_val, 4, 1, f); break; + case CTL_M68KPC: + fread(&val, 4, 1, f); + if (SekPc != val) { + printf("m68k: %08x %08x\n", SekPc, val); + bad = 1; + } + break; default: if (code < offsetof(SH2, read8_map) / 4) fread(regs_o + code, 4, 1, f); @@ -304,12 +357,9 @@ void do_sh2_cmp(SH2 *current) end: printf("--\n"); - csh2 = current->is_slave ? 's' : 'm'; - for (i = 0; i < 16/2; i++) - printf("%csh2 r%d: %08x r%02d: %08x\n", csh2, - i, sh2o->r[i], i+8, sh2o->r[i+8]); - printf("%csh2 PC: %08x , %08x\n", csh2, sh2o->pc, sh2o->ppc); - printf("%csh2 SR: %03x PR: %08x\n", csh2, sh2o->sr, sh2o->pr); + dump_regs(sh2o); + if (current->is_slave != current_slave) + dump_regs(&sh2ref[current->is_slave ^ 1]); PDebugDumpMem(); exit(1); } diff --git a/pico/pico.c b/pico/pico.c index 20648f0..9a1faca 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -145,6 +145,10 @@ int PicoReset(void) if (Pico.romsize <= 0) return 1; +#ifdef DRC_CMP + PicoOpt |= POPT_DIS_VDP_FIFO|POPT_DIS_IDLE_DET; +#endif + /* must call now, so that banking is reset, and correct vectors get fetched */ if (PicoResetHook) PicoResetHook(); diff --git a/pico/pico_int.h b/pico/pico_int.h index 420e82c..a654c5a 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -244,6 +244,7 @@ extern SH2 sh2s[2]; } \ } while (0) # define ash2_cycles_done(sh2) ((sh2)->cycles_timeslice - (sh2)->icount) +# define sh2_pc(c) (c) ? ssh2.ppc : msh2.ppc #else # define ash2_end_run(sh2, after) do { \ int left = (sh2)->sr >> 12; \ @@ -254,10 +255,9 @@ extern SH2 sh2s[2]; } \ } while (0) # define ash2_cycles_done(sh2) ((sh2)->cycles_timeslice - ((sh2)->sr >> 12)) +# define sh2_pc(c) (c) ? ssh2.pc : msh2.pc #endif -//#define sh2_pc(c) (c) ? ssh2.ppc : msh2.ppc -#define sh2_pc(c) (c) ? ssh2.pc : msh2.pc #define sh2_reg(c, x) (c) ? ssh2.r[x] : msh2.r[x] #define sh2_gbr(c) (c) ? ssh2.gbr : msh2.gbr #define sh2_vbr(c) (c) ? ssh2.vbr : msh2.vbr -- 2.39.2