From: Paul Cercueil Date: Fri, 17 Jan 2025 00:25:17 +0000 (+0100) Subject: lightrec: Add LIGHTREC_DEBUG functionality X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=97fa754ea10367f512b08c11c6f661d0beb1934f;p=pcsx_rearmed.git lightrec: Add LIGHTREC_DEBUG functionality When set, Lightrec will be built with the debug log level, the built-in disassembler for PSX code and JIT code (requires binutils), and support outputing data to the big-ass debugger (if the proper environment variables are set). Signed-off-by: Paul Cercueil --- diff --git a/Makefile b/Makefile index 7b9ac5ff..ec07225e 100644 --- a/Makefile +++ b/Makefile @@ -118,13 +118,22 @@ endif ifeq "$(DYNAREC)" "lightrec" CFLAGS += -Ideps/lightning/include -Ideps/lightrec -Iinclude/lightning -Iinclude/lightrec \ -DLIGHTREC -DLIGHTREC_STATIC +ifeq ($(LIGHTREC_DEBUG),1) +deps/lightrec/%.o: CFLAGS += -DLOG_LEVEL=DEBUG_L +libpcsxcore/lightrec/plugin.o: CFLAGS += -DLIGHTREC_DEBUG=1 +frontend/main.o: CFLAGS += -DLIGHTREC_DEBUG=1 +deps/lightning/%.o: CFLAGS += -DDISASSEMBLER=1 -DBINUTILS_2_38=1 -DBINUTILS_2_29=1 \ + -DHAVE_DISASSEMBLE_INIT_FOR_TARGET=1 -DPACKAGE_VERSION=1 +LDFLAGS += -lopcodes -lbfd +endif LIGHTREC_CUSTOM_MAP ?= 0 LIGHTREC_CUSTOM_MAP_OBJ ?= libpcsxcore/lightrec/mem.o LIGHTREC_THREADED_COMPILER ?= 0 LIGHTREC_CODE_INV ?= 0 CFLAGS += -DLIGHTREC_CUSTOM_MAP=$(LIGHTREC_CUSTOM_MAP) \ -DLIGHTREC_CODE_INV=$(LIGHTREC_CODE_INV) \ - -DLIGHTREC_ENABLE_THREADED_COMPILER=$(LIGHTREC_THREADED_COMPILER) + -DLIGHTREC_ENABLE_THREADED_COMPILER=$(LIGHTREC_THREADED_COMPILER) \ + -DLIGHTREC_ENABLE_DISASSEMBLER=$(or $(LIGHTREC_DEBUG),0) ifeq ($(LIGHTREC_CUSTOM_MAP),1) LDLIBS += -lrt OBJS += $(LIGHTREC_CUSTOM_MAP_OBJ) diff --git a/frontend/main.c b/frontend/main.c index 2dd5ca4c..b2a4fea4 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -737,7 +737,9 @@ int main(int argc, char *argv[]) else menu_loop(); +#ifndef LIGHTREC_DEBUG pl_start_watchdog(); +#endif while (!g_emu_want_quit) { diff --git a/include/lightrec/lightrec-config.h b/include/lightrec/lightrec-config.h index 3d4b81e6..8453fe46 100644 --- a/include/lightrec/lightrec-config.h +++ b/include/lightrec/lightrec-config.h @@ -8,7 +8,7 @@ #define ENABLE_THREADED_COMPILER LIGHTREC_ENABLE_THREADED_COMPILER #define ENABLE_FIRST_PASS 1 -#define ENABLE_DISASSEMBLER 0 +#define ENABLE_DISASSEMBLER LIGHTREC_ENABLE_DISASSEMBLER #define ENABLE_CODE_BUFFER 1 #define HAS_DEFAULT_ELM 1 diff --git a/jni/Android.mk b/jni/Android.mk index 8439f3d7..0fe5cb95 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -134,6 +134,7 @@ HAVE_ARI64=0 HAVE_LIGHTREC=0 LIGHTREC_CUSTOM_MAP=0 LIGHTREC_THREADED_COMPILER=0 +LIGHTREC_DEBUG=0 HAVE_GPU_NEON=0 ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) HAVE_ARI64=1 @@ -154,6 +155,7 @@ else endif COREFLAGS += -DLIGHTREC_CUSTOM_MAP=$(LIGHTREC_CUSTOM_MAP) COREFLAGS += -DLIGHTREC_ENABLE_THREADED_COMPILER=$(LIGHTREC_THREADED_COMPILER) + COREFLAGS += -DLIGHTREC_ENABLE_DISASSEMBLER=$(or $(LIGHTREC_DEBUG),0) ifeq ($(HAVE_ARI64),1) SOURCES_C += $(DYNAREC_DIR)/new_dynarec.c \ diff --git a/libpcsxcore/lightrec/plugin.c b/libpcsxcore/lightrec/plugin.c index d62f35bd..0ca44e44 100644 --- a/libpcsxcore/lightrec/plugin.c +++ b/libpcsxcore/lightrec/plugin.c @@ -72,6 +72,9 @@ static bool use_lightrec_interpreter; static bool block_stepping; //static bool use_pcsx_interpreter; #define use_pcsx_interpreter 0 +static bool ram_disabled; +static bool lightrec_debug, lightrec_very_debug; +static u32 lightrec_begin_cycles; extern u32 lightrec_hacks; @@ -340,6 +343,8 @@ static void lightrec_enable_ram(struct lightrec_state *state, bool enable) memcpy(psxM, cache_buf, sizeof(cache_buf)); else memcpy(cache_buf, psxM, sizeof(cache_buf)); + + ram_disabled = !enable; } static bool lightrec_can_hw_direct(u32 kaddr, bool is_write, u8 size) @@ -465,6 +470,16 @@ static int lightrec_plugin_init(void) use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER"); +#ifdef LIGHTREC_DEBUG + char *cycles = getenv("LIGHTREC_BEGIN_CYCLES"); + + lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG"); + lightrec_debug = lightrec_very_debug || !!getenv("LIGHTREC_DEBUG"); + + if (cycles) + lightrec_begin_cycles = (unsigned int) strtol(cycles, NULL, 0); +#endif + lightrec_state = lightrec_init(LIGHTREC_PROG_NAME, lightrec_map, ARRAY_SIZE(lightrec_map), &lightrec_ops); @@ -481,6 +496,104 @@ static int lightrec_plugin_init(void) return 0; } +static u32 do_calculate_hash(const void *buffer, u32 count, u32 needle, bool le) +{ + unsigned int i; + const u32 *data = (const u32 *) buffer; + u32 hash = needle; + + count /= 4; + for(i = 0; i < count; ++i) { + hash += le ? LE32TOH(data[i]) : data[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash; +} + +static u32 hash_calculate_le(const void *buffer, u32 count) +{ + return do_calculate_hash(buffer, count, 0xffffffff, true); +} + +u32 hash_calculate(const void *buffer, u32 count) +{ + return do_calculate_hash(buffer, count, 0xffffffff, false); +} + +static u32 hash_calculate_ram(const void *buffer, u32 ram_size) +{ + u32 hash; + + if (ram_disabled) + hash = hash_calculate_le(cache_buf, sizeof(cache_buf)); + else + hash = hash_calculate_le(buffer, sizeof(cache_buf)); + + return do_calculate_hash(buffer + sizeof(cache_buf), + ram_size - sizeof(cache_buf), + hash, true); +} + +static const char * const mips_regs[] = { + "zero", + "at", + "v0", "v1", + "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", + "k0", "k1", + "gp", "sp", "fp", "ra", + "lo", "hi", +}; + +static void print_for_big_ass_debugger(void) +{ + struct lightrec_registers *regs; + unsigned int i; + + regs = lightrec_get_registers(lightrec_state); + + printf("CYCLE 0x%08x PC 0x%08x", psxRegs.cycle, psxRegs.pc); + + if (lightrec_very_debug) + printf(" RAM 0x%08x SCRATCH 0x%08x HW 0x%08x", + hash_calculate_ram(psxM, 0x200000), + hash_calculate_le(psxH, 0x400), + hash_calculate_le(psxH + 0x1000, 0x2000)); + + printf(" CP0 0x%08x CP2D 0x%08x CP2C 0x%08x INT 0x%04x INTCYCLE 0x%08x GPU 0x%08x", + hash_calculate(regs->cp0, sizeof(regs->cp0)), + hash_calculate(regs->cp2d, sizeof(regs->cp2d)), + hash_calculate(regs->cp2c, sizeof(regs->cp2c)), + psxRegs.interrupt, + hash_calculate(psxRegs.intCycle, sizeof(psxRegs.intCycle)), + LE32TOH(HW_GPU_STATUS)); + + if (lightrec_very_debug) { + for (i = 0; i < 32; i++) + printf(" CP2D%u 0x%08x", i, regs->cp2d[i]); + for (i = 0; i < 32; i++) + printf(" CP2C%u 0x%08x", i, regs->cp2c[i]); + } + + if (lightrec_very_debug) + for (i = 0; i < 34; i++) + printf(" %s 0x%08x", mips_regs[i], regs->gpr[i]); + else + printf(" GPR 0x%08x", + hash_calculate(regs->gpr, sizeof(regs->gpr))); + printf("\n"); + + fflush(stdout); +} + static void lightrec_plugin_sync_regs_to_pcsx(bool need_cp2); static void lightrec_plugin_sync_regs_from_pcsx(bool need_cp2); @@ -488,6 +601,7 @@ static void lightrec_plugin_execute_internal(bool block_only) { struct lightrec_registers *regs; u32 flags, cycles_pcsx; + u32 old_pc = psxRegs.pc; regs = lightrec_get_registers(lightrec_state); gen_interupt((psxCP0Regs *)regs->cp0); @@ -522,6 +636,8 @@ static void lightrec_plugin_execute_internal(bool block_only) if (flags & LIGHTREC_EXIT_SEGFAULT) { fprintf(stderr, "Exiting at cycle 0x%08x\n", psxRegs.cycle); + if (lightrec_debug) + print_for_big_ass_debugger(); exit(1); } @@ -542,6 +658,10 @@ static void lightrec_plugin_execute_internal(bool block_only) } } + if (lightrec_debug && psxRegs.cycle >= lightrec_begin_cycles && psxRegs.pc != old_pc) { + print_for_big_ass_debugger(); + } + if ((regs->cp0[13] & regs->cp0[12] & 0x300) && (regs->cp0[12] & 0x1)) { /* Handle software interrupts */ regs->cp0[13] &= ~0x7c; @@ -552,7 +672,7 @@ static void lightrec_plugin_execute_internal(bool block_only) static void lightrec_plugin_execute(psxRegisters *regs) { while (!regs->stop) - lightrec_plugin_execute_internal(false); + lightrec_plugin_execute_internal(lightrec_very_debug); } static void lightrec_plugin_execute_block(psxRegisters *regs,