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)
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;
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)
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);
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);
{
struct lightrec_registers *regs;
u32 flags, cycles_pcsx;
+ u32 old_pc = psxRegs.pc;
regs = lightrec_get_registers(lightrec_state);
gen_interupt((psxCP0Regs *)regs->cp0);
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);
}
}
}
+ 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;
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,