From: notaz Date: Sat, 10 Aug 2013 14:57:54 +0000 (+0300) Subject: some new cpu debug code X-Git-Tag: v1.85~2^2~40 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12da51c27a8d1c1205d8f0f01bbc4814c46e79ce;p=picodrive.git some new cpu debug code --- diff --git a/Makefile b/Makefile index db145a5b..e6e3b2fc 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,8 @@ CFLAGS += -O2 -DNDEBUG endif #CFLAGS += -DEVT_LOG #CFLAGS += -DDRC_CMP -#drc_debug = 4 +#cpu_cmp = 1 +#drc_debug = 3 #profile = 1 diff --git a/cpu/cyclone b/cpu/cyclone index 194104e3..1f9661c5 160000 --- a/cpu/cyclone +++ b/cpu/cyclone @@ -1 +1 @@ -Subproject commit 194104e334f7c26015b99c862486a73be0d80162 +Subproject commit 1f9661c5a2919ba91c0f4b89985e0712871e5762 diff --git a/cpu/cyclone_config.h b/cpu/cyclone_config.h index af9ab5e7..7f9690d0 100644 --- a/cpu/cyclone_config.h +++ b/cpu/cyclone_config.h @@ -19,7 +19,7 @@ #define MEMHANDLERS_NEED_CYCLES 1 #define MEMHANDLERS_CHANGE_PC 0 #define MEMHANDLERS_CHANGE_FLAGS 0 -#define MEMHANDLERS_CHANGE_CYCLES 0 +#define MEMHANDLERS_CHANGE_CYCLES 1 #define MEMHANDLERS_DIRECT_PREFIX "cyclone_" diff --git a/cpu/sh2/sh2.c b/cpu/sh2/sh2.c index 847035a5..7b83cf21 100644 --- a/cpu/sh2/sh2.c +++ b/cpu/sh2/sh2.c @@ -136,15 +136,6 @@ void sh2_unpack(SH2 *sh2, const unsigned char *buff) static SH2 sh2ref[2]; 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, -}; static unsigned int local_read32(SH2 *sh2, u32 a) { @@ -176,12 +167,6 @@ static unsigned int local_read32(SH2 *sh2, u32 a) return 0; } -static void write_uint(unsigned char ctl, unsigned int v) -{ - fwrite(&ctl, 1, 1, f); - fwrite(&v, sizeof(v), 1, f); -} - void do_sh2_trace(SH2 *current, int cycles) { static int current_slave = -1; @@ -193,39 +178,36 @@ void do_sh2_trace(SH2 *current, int cycles) u32 val; int i; - if (f == NULL) - f = fopen("tracelog", "wb"); - if (SekPc != current_m68k_pc) { current_m68k_pc = SekPc; - write_uint(CTL_M68KPC, current_m68k_pc); + tl_write_uint(CTL_M68KPC, current_m68k_pc); } if (current->is_slave != current_slave) { current_slave = current->is_slave; v = CTL_MASTERSLAVE | current->is_slave; - fwrite(&v, 1, 1, f); + tl_write(&v, sizeof(v)); } for (i = 0; i < offsetof(SH2, read8_map) / 4; i++) { if (i == 17) // ppc continue; if (regs_a[i] != regs_o[i]) { - write_uint(i, regs_a[i]); + tl_write_uint(CTL_SH2_R + i, regs_a[i]); regs_o[i] = regs_a[i]; } } if (current->ea != sh2o->ea) { - write_uint(CTL_EA, current->ea); + tl_write_uint(CTL_EA, current->ea); sh2o->ea = current->ea; } val = local_read32(current, current->ea); if (mem_val != val) { - write_uint(CTL_EAVAL, val); + tl_write_uint(CTL_EAVAL, val); mem_val = val; } - write_uint(CTL_CYCLES, cycles); + tl_write_uint(CTL_CYCLES, cycles); } static const char *regnames[] = { @@ -264,17 +246,14 @@ void do_sh2_cmp(SH2 *current) int cycles; int i, ret; - if (f == NULL) { - f = fopen("tracelog", "rb"); - sh2ref[1].is_slave = 1; - } + sh2ref[1].is_slave = 1; while (1) { - ret = fread(&code, 1, 1, f); + ret = tl_read(&code, 1); if (ret <= 0) break; if (code == CTL_CYCLES) { - fread(&cycles_o, 1, 4, f); + tl_read(&cycles_o, 4); break; } @@ -284,23 +263,27 @@ void do_sh2_cmp(SH2 *current) current_slave = code & 1; break; case CTL_EA: - fread(&sh2o->ea, 4, 1, f); + tl_read_uint(&sh2o->ea); break; case CTL_EAVAL: - fread(¤t_val, 4, 1, f); + tl_read_uint(¤t_val); break; case CTL_M68KPC: - fread(&val, 4, 1, f); + tl_read_uint(&val); 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); - else { - printf("invalid code: %02x\n", code); + if (CTL_SH2_R <= code && code < CTL_SH2_R + + offsetof(SH2, read8_map) / 4) + { + tl_read_uint(regs_o + code - CTL_SH2_R); + } + else + { + printf("wrong code: %02x\n", code); goto end; } break; diff --git a/pico/debug.c b/pico/debug.c index 03451201..9cb93b26 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -40,7 +40,7 @@ char *PDebugMain(void) sprintf(dstrp, "mode set 4: %02x\n", (r=reg[0xC])); MVP; sprintf(dstrp, "interlace: %i%i, cells: %i, shadow: %i\n", bit(r,2), bit(r,1), (r&0x80) ? 40 : 32, bit(r,3)); MVP; sprintf(dstrp, "scroll size: w: %i, h: %i SRAM: %i; eeprom: %i (%i)\n", reg[0x10]&3, (reg[0x10]&0x30)>>4, - !!(SRam.flags & SRF_ENABLED), !!(SRam.flags & SRF_EEPROM), SRam.eeprom_type); MVP; + !!(SRam.flags & SRF_ENABLED), !!(SRam.flags & SRF_EEPROM), SRam.eeprom_type); MVP; sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", SRam.start, SRam.end, Pico.m.sram_reg); MVP; sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP; sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDoneT()); MVP; @@ -535,4 +535,35 @@ void pevt_dump(void) } #endif +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) +static FILE *tl_f; + +void tl_write(const void *ptr, size_t size) +{ + if (tl_f == NULL) + tl_f = fopen("tracelog", "wb"); + + fwrite(ptr, 1, size, tl_f); +} + +void tl_write_uint(unsigned char ctl, unsigned int v) +{ + tl_write(&ctl, sizeof(ctl)); + tl_write(&v, sizeof(v)); +} + +int tl_read(void *ptr, size_t size) +{ + if (tl_f == NULL) + tl_f = fopen("tracelog", "rb"); + + return fread(ptr, 1, size, tl_f); +} + +int tl_read_uint(void *ptr) +{ + return tl_read(ptr, 4); +} +#endif + // vim:shiftwidth=2:ts=2:expandtab diff --git a/pico/debug.h b/pico/debug.h index 53dc6680..fcfdc079 100644 --- a/pico/debug.h +++ b/pico/debug.h @@ -9,3 +9,23 @@ void PDebugDumpMem(void); void PDebugZ80Frame(void); void PDebugCPUStep(void); +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) +enum ctl_byte { + CTL_68K_SLAVE = 0x02, + CTL_68K_PC = 0x04, + CTL_68K_SR = 0x05, + CTL_68K_CYCLES = 0x06, + CTL_68K_R = 0x10, // .. 0x20 + CTL_MASTERSLAVE = 0x80, + CTL_EA = 0x82, + CTL_EAVAL = 0x83, + CTL_M68KPC = 0x84, + CTL_CYCLES = 0x85, + CTL_SH2_R = 0x90, // .. 0xa8 +}; + +void tl_write(const void *ptr, size_t size); +void tl_write_uint(unsigned char ctl, unsigned int v); +int tl_read(void *ptr, size_t size); +int tl_read_uint(void *ptr); +#endif diff --git a/pico/m68kif_cyclone.s b/pico/m68kif_cyclone.s index f8b6927c..a0a508cd 100644 --- a/pico/m68kif_cyclone.s +++ b/pico/m68kif_cyclone.s @@ -24,16 +24,18 @@ cyclone_checkpc: ldr r1, [r7, #0x60] @ membase sub r0, r0, r1 - bic r0, r0, #0xff000000 - bics r0, r0, #1 + and r3, r0, #0xff000000 + bic r0, r0, #1 + bics r2, r0, #0xff000000 beq crashed ldr r1, [r7, #0x6c] @ read16 map - mov r2, r0, lsr #M68K_MEM_SHIFT + mov r2, r2, lsr #M68K_MEM_SHIFT ldr r1, [r1, r2, lsl #2] movs r1, r1, lsl #1 bcs crashed + sub r1, r1, r3 str r1, [r7, #0x60] @ membase add r0, r0, r1 bx lr diff --git a/pico/pico.c b/pico/pico.c index 80ffb90e..747c6266 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -146,7 +146,7 @@ int PicoReset(void) if (Pico.romsize <= 0) return 1; -#ifdef DRC_CMP +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) PicoOpt |= POPT_DIS_VDP_FIFO|POPT_DIS_IDLE_DET; #endif diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 9099c855..3383b131 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -50,6 +50,7 @@ static __inline void SekRunM68k(int cyc) #endif out: + SekTrace(0); pevt_log_m68k_o(EVT_RUN_END); pprof_end(m68k); } diff --git a/pico/pico_int.h b/pico/pico_int.h index 339d1bf1..9fcc6d4b 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -46,8 +46,10 @@ extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k; #define SekEndTimesliceS68k(after) PicoCpuCS68k.cycles=after #define SekPc (PicoCpuCM68k.pc-PicoCpuCM68k.membase) #define SekPcS68k (PicoCpuCS68k.pc-PicoCpuCS68k.membase) -#define SekDar(x) (x < 8 ? PicoCpuCM68k.d[x] : PicoCpuCM68k.a[x - 8]) +#define SekDar(x) (x < 8 ? PicoCpuCM68k.d[x] : PicoCpuCM68k.a[x - 8]) +#define SekDarS68k(x) (x < 8 ? PicoCpuCS68k.d[x] : PicoCpuCS68k.a[x - 8]) #define SekSr CycloneGetSr(&PicoCpuCM68k) +#define SekSrS68k CycloneGetSr(&PicoCpuCS68k) #define SekSetStop(x) { PicoCpuCM68k.state_flags&=~1; if (x) { PicoCpuCM68k.state_flags|=1; PicoCpuCM68k.cycles=0; } } #define SekSetStopS68k(x) { PicoCpuCS68k.state_flags&=~1; if (x) { PicoCpuCS68k.state_flags|=1; PicoCpuCS68k.cycles=0; } } #define SekIsStoppedM68k() (PicoCpuCM68k.state_flags&1) @@ -74,8 +76,10 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; #define SekEndTimesliceS68k(after) PicoCpuFS68k.io_cycle_counter=after #define SekPc fm68k_get_pc(&PicoCpuFM68k) #define SekPcS68k fm68k_get_pc(&PicoCpuFS68k) -#define SekDar(x) (x < 8 ? PicoCpuFM68k.dreg[x].D : PicoCpuFM68k.areg[x - 8].D) +#define SekDar(x) (x < 8 ? PicoCpuFM68k.dreg[x].D : PicoCpuFM68k.areg[x - 8].D) +#define SekDarS68k(x) (x < 8 ? PicoCpuFS68k.dreg[x].D : PicoCpuFS68k.areg[x - 8].D) #define SekSr PicoCpuFM68k.sr +#define SekSrS68k PicoCpuFS68k.sr #define SekSetStop(x) { \ PicoCpuFM68k.execinfo &= ~FM68K_HALTED; \ if (x) { PicoCpuFM68k.execinfo |= FM68K_HALTED; PicoCpuFM68k.io_cycle_counter = 0; } \ @@ -109,8 +113,10 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; #define SekEndTimesliceS68k(after) PicoCpuMS68k.cyc_remaining_cycles=after #define SekPc m68k_get_reg(&PicoCpuMM68k, M68K_REG_PC) #define SekPcS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_PC) -#define SekDar(x) PicoCpuMM68k.dar[x] -#define SekSr m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR) +#define SekDar(x) PicoCpuMM68k.dar[x] +#define SekDarS68k(x) PicoCpuMS68k.dar[x] +#define SekSr m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR) +#define SekSrS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_SR) #define SekSetStop(x) { \ if(x) { SET_CYCLES(0); PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \ else PicoCpuMM68k.stopped=0; \ @@ -633,6 +639,11 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub); void SekStepM68k(void); void SekInitIdleDet(void); void SekFinishIdleDet(void); +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) +void SekTrace(int is_s68k); +#else +#define SekTrace(x) +#endif // cd/sek.c PICO_INTERNAL void SekInitS68k(void); diff --git a/pico/sek.c b/pico/sek.c index 85bfd287..2fe77cbb 100644 --- a/pico/sek.c +++ b/pico/sek.c @@ -420,6 +420,122 @@ void SekFinishIdleDet(void) } +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) +#include "debug.h" + +struct ref_68k { + u32 dar[16]; + u32 pc; + u32 sr; + u32 cycles; + u32 pc_prev; +}; +struct ref_68k ref_68ks[2]; +static int current_68k; + +void SekTrace(int is_s68k) +{ + struct ref_68k *x68k = &ref_68ks[is_s68k]; + u32 pc = is_s68k ? SekPcS68k : SekPc; + u32 sr = is_s68k ? SekSrS68k : SekSr; + u32 cycles = is_s68k ? SekCycleCntS68k : SekCycleCnt; + u32 r; + u8 cmd; +#ifdef CPU_CMP_W + int i; + + if (is_s68k != current_68k) { + current_68k = is_s68k; + cmd = CTL_68K_SLAVE | current_68k; + tl_write(&cmd, sizeof(cmd)); + } + if (pc != x68k->pc) { + x68k->pc = pc; + tl_write_uint(CTL_68K_PC, x68k->pc); + } + if (sr != x68k->sr) { + x68k->sr = sr; + tl_write_uint(CTL_68K_SR, x68k->sr); + } + for (i = 0; i < 16; i++) { + r = is_s68k ? SekDarS68k(i) : SekDar(i); + if (r != x68k->dar[i]) { + x68k->dar[i] = r; + tl_write_uint(CTL_68K_R + i, r); + } + } + tl_write_uint(CTL_68K_CYCLES, cycles); +#else + int i, bad = 0; + + while (1) + { + int ret = tl_read(&cmd, sizeof(cmd)); + if (ret == 0) { + elprintf(EL_STATUS, "EOF"); + exit(1); + } + switch (cmd) { + case CTL_68K_SLAVE: + case CTL_68K_SLAVE + 1: + current_68k = cmd & 1; + break; + case CTL_68K_PC: + tl_read_uint(&x68k->pc); + break; + case CTL_68K_SR: + tl_read_uint(&x68k->sr); + break; + case CTL_68K_CYCLES: + tl_read_uint(&x68k->cycles); + goto breakloop; + default: + if (CTL_68K_R <= cmd && cmd < CTL_68K_R + 0x10) + tl_read_uint(&x68k->dar[cmd - CTL_68K_R]); + else + elprintf(EL_STATUS, "invalid cmd: %02x", cmd); + } + } + +breakloop: + if (is_s68k != current_68k) { + printf("bad 68k: %d %d\n", is_s68k, current_68k); + bad = 1; + } + if (cycles != x68k->cycles) { + printf("bad cycles: %u %u\n", cycles, x68k->cycles); + bad = 1; + } + if ((pc ^ x68k->pc) & 0xffffff) { + printf("bad PC: %08x %08x\n", pc, x68k->pc); + bad = 1; + } + if (sr != x68k->sr) { + printf("bad SR: %03x %03x\n", sr, x68k->sr); + bad = 1; + } + for (i = 0; i < 16; i++) { + r = is_s68k ? SekDarS68k(i) : SekDar(i); + if (r != x68k->dar[i]) { + printf("bad %c%d: %08x %08x\n", i < 8 ? 'D' : 'A', i & 7, + r, x68k->dar[i]); + bad = 1; + } + } + if (bad) { + for (i = 0; i < 8; i++) + printf("D%d: %08x A%d: %08x\n", i, x68k->dar[i], + i, x68k->dar[i + 8]); + printf("PC: %08x, %08x\n", x68k->pc, x68k->pc_prev); + + PDebugDumpMem(); + exit(1); + } + x68k->pc_prev = x68k->pc; +#endif +} +#endif // CPU_CMP_* + #if defined(EMU_M68K) && M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER static unsigned char op_flags[0x400000/2] = { 0, }; static int atexit_set = 0; @@ -447,3 +563,5 @@ void instruction_hook(void) op_flags[REG_PC/2] = 1; } #endif + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/platform/common/common.mak b/platform/common/common.mak index 17e540fb..a365abc6 100644 --- a/platform/common/common.mak +++ b/platform/common/common.mak @@ -30,6 +30,13 @@ SRCS_COMMON += $(R)cpu/debug.c LDFLAGS += -lreadline endif endif +ifeq "$(cpu_cmp)" "1" +ifdef cpu_cmp_w +DEFINES += CPU_CMP_W +else +DEFINES += CPU_CMP_R +endif # cpu_cmp_w +endif ifeq "$(pprof)" "1" DEFINES += PPROF SRCS_COMMON += $(R)platform/linux/pprof.c @@ -157,10 +164,6 @@ SRCS_COMMON += $(R)cpu/sh2/mame/sh2dasm.c SRCS_COMMON += $(R)platform/libpicofe/linux/host_dasm.c LDFLAGS += -lbfd -lopcodes -liberty endif -ifeq "$(drc_debug_interp)" "1" -DEFINES += DRC_DEBUG_INTERP -use_sh2mame = 1 -endif endif # use_sh2drc # ifeq "$(use_sh2mame)" "1" @@ -183,7 +186,7 @@ $(FR)cpu/cyclone/Cyclone.h: $(FR)cpu/cyclone/Cyclone.s: @echo building Cyclone... - @make -C $(R)cpu/cyclone/ CONFIG_FILE='\"../cyclone_config.h\"' + @make -C $(R)cpu/cyclone/ CONFIG_FILE=../cyclone_config.h $(FR)cpu/musashi/m68kops.c: @make -C $(R)cpu/musashi