diff options
author | Alexis PUSKARCZYK | 2016-12-19 10:18:15 +0100 |
---|---|---|
committer | Alexis PUSKARCZYK | 2016-12-19 10:18:15 +0100 |
commit | ea4db4b5e14d27f9820cc72ecc7b244c1c2b9cb9 (patch) | |
tree | 1c711b85837e96914b692778376f7cf2dc51927f /libpcsxcore/new_dynarec/backends | |
parent | 127622a0091a7a54c8c32069bdd262ad6d402b16 (diff) | |
parent | 30373a821c80e223d5c592ccce95377ff57b4998 (diff) | |
download | pcsx_rearmed-ea4db4b5e14d27f9820cc72ecc7b244c1c2b9cb9.tar.gz pcsx_rearmed-ea4db4b5e14d27f9820cc72ecc7b244c1c2b9cb9.tar.bz2 pcsx_rearmed-ea4db4b5e14d27f9820cc72ecc7b244c1c2b9cb9.zip |
Merge branch 'master' of https://github.com/libretro/pcsx_rearmed into master_merged
Diffstat (limited to 'libpcsxcore/new_dynarec/backends')
-rw-r--r-- | libpcsxcore/new_dynarec/backends/psx/emu_if.c | 695 | ||||
-rw-r--r-- | libpcsxcore/new_dynarec/backends/psx/emu_if.h | 108 | ||||
-rw-r--r-- | libpcsxcore/new_dynarec/backends/psx/pcsxmem.c | 494 | ||||
-rw-r--r-- | libpcsxcore/new_dynarec/backends/psx/pcsxmem.h | 9 | ||||
-rw-r--r-- | libpcsxcore/new_dynarec/backends/psx/pcsxmem_inline.c | 66 |
5 files changed, 1372 insertions, 0 deletions
diff --git a/libpcsxcore/new_dynarec/backends/psx/emu_if.c b/libpcsxcore/new_dynarec/backends/psx/emu_if.c new file mode 100644 index 0000000..6dc48e2 --- /dev/null +++ b/libpcsxcore/new_dynarec/backends/psx/emu_if.c @@ -0,0 +1,695 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2010-2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <stdio.h> + +#include "emu_if.h" +#include "pcsxmem.h" +#include "../../../psxhle.h" +#include "../../../r3000a.h" +#include "../../../cdrom.h" +#include "../../../psxdma.h" +#include "../../../mdec.h" +#include "../../../gte_arm.h" +#include "../../../gte_neon.h" +#define FLAGLESS +#include "../../../gte.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +//#define evprintf printf +#define evprintf(...) + +char invalid_code[0x100000]; +static u32 scratch_buf[8*8*2] __attribute__((aligned(64))); +u32 event_cycles[PSXINT_COUNT]; + +static void schedule_timeslice(void) +{ + u32 i, c = psxRegs.cycle; + u32 irqs = psxRegs.interrupt; + s32 min, dif; + + min = PSXCLK; + for (i = 0; irqs != 0; i++, irqs >>= 1) { + if (!(irqs & 1)) + continue; + dif = event_cycles[i] - c; + //evprintf(" ev %d\n", dif); + if (0 < dif && dif < min) + min = dif; + } + next_interupt = c + min; +} + +typedef void (irq_func)(); + +static irq_func * const irq_funcs[] = { + [PSXINT_SIO] = sioInterrupt, + [PSXINT_CDR] = cdrInterrupt, + [PSXINT_CDREAD] = cdrReadInterrupt, + [PSXINT_GPUDMA] = gpuInterrupt, + [PSXINT_MDECOUTDMA] = mdec1Interrupt, + [PSXINT_SPUDMA] = spuInterrupt, + [PSXINT_MDECINDMA] = mdec0Interrupt, + [PSXINT_GPUOTCDMA] = gpuotcInterrupt, + [PSXINT_CDRDMA] = cdrDmaInterrupt, + [PSXINT_CDRLID] = cdrLidSeekInterrupt, + [PSXINT_CDRPLAY] = cdrPlayInterrupt, + [PSXINT_SPU_UPDATE] = spuUpdate, + [PSXINT_RCNT] = psxRcntUpdate, +}; + +/* local dupe of psxBranchTest, using event_cycles */ +static void irq_test(void) +{ + u32 irqs = psxRegs.interrupt; + u32 cycle = psxRegs.cycle; + u32 irq, irq_bits; + + // irq_funcs() may queue more irqs + psxRegs.interrupt = 0; + + for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) { + if (!(irq_bits & 1)) + continue; + if ((s32)(cycle - event_cycles[irq]) >= 0) { + irqs &= ~(1 << irq); + irq_funcs[irq](); + } + } + psxRegs.interrupt |= irqs; + + if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) { + psxException(0x400, 0); + pending_exception = 1; + } +} + +void gen_interupt() +{ + evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt); + + irq_test(); + //psxBranchTest(); + //pending_exception = 1; + + schedule_timeslice(); + + evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle, + next_interupt, next_interupt - psxRegs.cycle); +} + +// from interpreter +extern void MTC0(int reg, u32 val); + +void pcsx_mtc0(u32 reg, u32 val) +{ + evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle); + MTC0(reg, val); + gen_interupt(); + if (Cause & Status & 0x0300) // possible sw irq + pending_exception = 1; +} + +void pcsx_mtc0_ds(u32 reg, u32 val) +{ + evprintf("MTC0 %d #%x @%08x %u\n", reg, val, psxRegs.pc, psxRegs.cycle); + MTC0(reg, val); +} + +void new_dyna_before_save(void) +{ + psxRegs.interrupt &= ~(1 << PSXINT_RCNT); // old savestate compat + + // psxRegs.intCycle is always maintained, no need to convert +} + +void new_dyna_after_save(void) +{ + psxRegs.interrupt |= 1 << PSXINT_RCNT; +} + +static void new_dyna_restore(void) +{ + int i; + for (i = 0; i < PSXINT_COUNT; i++) + event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle; + + event_cycles[PSXINT_RCNT] = psxNextsCounter + psxNextCounter; + psxRegs.interrupt |= 1 << PSXINT_RCNT; + psxRegs.interrupt &= (1 << PSXINT_COUNT) - 1; + + new_dyna_pcsx_mem_load_state(); +} + +void new_dyna_freeze(void *f, int mode) +{ + const char header_save[8] = "ariblks"; + uint32_t addrs[1024 * 4]; + int32_t size = 0; + int bytes; + char header[8]; + + if (mode != 0) { // save + size = new_dynarec_save_blocks(addrs, sizeof(addrs)); + if (size == 0) + return; + + SaveFuncs.write(f, header_save, sizeof(header_save)); + SaveFuncs.write(f, &size, sizeof(size)); + SaveFuncs.write(f, addrs, size); + } + else { + new_dyna_restore(); + + bytes = SaveFuncs.read(f, header, sizeof(header)); + if (bytes != sizeof(header) || strcmp(header, header_save)) { + if (bytes > 0) + SaveFuncs.seek(f, -bytes, SEEK_CUR); + return; + } + SaveFuncs.read(f, &size, sizeof(size)); + if (size <= 0) + return; + if (size > sizeof(addrs)) { + bytes = size - sizeof(addrs); + SaveFuncs.seek(f, bytes, SEEK_CUR); + size = sizeof(addrs); + } + bytes = SaveFuncs.read(f, addrs, size); + if (bytes != size) + return; + + new_dynarec_load_blocks(addrs, size); + } + + //printf("drc: %d block info entries %s\n", size/8, mode ? "saved" : "loaded"); +} + +/* GTE stuff */ +void *gte_handlers[64]; + +void *gte_handlers_nf[64] = { + NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00 + NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08 + gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10 + NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18 + gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20 + gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28 + gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30 + NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38 +}; + +const char *gte_regnames[64] = { + NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00 + NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08 + "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10 + NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18 + "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20 + "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28 + "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30 + NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38 +}; + +/* from gte.txt.. not sure if this is any good. */ +const char gte_cycletab[64] = { + /* 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0, + 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0, + 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39, +}; + +#define GCBIT(x) \ + (1ll << (32+x)) +#define GDBIT(x) \ + (1ll << (x)) +#define GCBITS3(b0,b1,b2) \ + (GCBIT(b0) | GCBIT(b1) | GCBIT(b2)) +#define GDBITS2(b0,b1) \ + (GDBIT(b0) | GDBIT(b1)) +#define GDBITS3(b0,b1,b2) \ + (GDBITS2(b0,b1) | GDBIT(b2)) +#define GDBITS4(b0,b1,b2,b3) \ + (GDBITS3(b0,b1,b2) | GDBIT(b3)) +#define GDBITS5(b0,b1,b2,b3,b4) \ + (GDBITS4(b0,b1,b2,b3) | GDBIT(b4)) +#define GDBITS6(b0,b1,b2,b3,b4,b5) \ + (GDBITS5(b0,b1,b2,b3,b4) | GDBIT(b5)) +#define GDBITS7(b0,b1,b2,b3,b4,b5,b6) \ + (GDBITS6(b0,b1,b2,b3,b4,b5) | GDBIT(b6)) +#define GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) \ + (GDBITS7(b0,b1,b2,b3,b4,b5,b6) | GDBIT(b7)) +#define GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) \ + (GDBITS8(b0,b1,b2,b3,b4,b5,b6,b7) | GDBIT(b8)) +#define GDBITS10(b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) \ + (GDBITS9(b0,b1,b2,b3,b4,b5,b6,b7,b8) | GDBIT(b9)) + +const uint64_t gte_reg_reads[64] = { + [GTE_RTPS] = 0x1f0000ff00000000ll | GDBITS7(0,1,13,14,17,18,19), + [GTE_NCLIP] = GDBITS3(12,13,14), + [GTE_OP] = GCBITS3(0,2,4) | GDBITS3(9,10,11), + [GTE_DPCS] = GCBITS3(21,22,23) | GDBITS4(6,8,21,22), + [GTE_INTPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22), + [GTE_MVMVA] = 0x00ffffff00000000ll | GDBITS9(0,1,2,3,4,5,9,10,11), // XXX: maybe decode further? + [GTE_NCDS] = 0x00ffff0000000000ll | GDBITS6(0,1,6,8,21,22), + [GTE_CDP] = 0x00ffe00000000000ll | GDBITS7(6,8,9,10,11,21,22), + [GTE_NCDT] = 0x00ffff0000000000ll | GDBITS8(0,1,2,3,4,5,6,8), + [GTE_NCCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22), + [GTE_CC] = 0x001fe00000000000ll | GDBITS6(6,9,10,11,21,22), + [GTE_NCS] = 0x001fff0000000000ll | GDBITS5(0,1,6,21,22), + [GTE_NCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6), + [GTE_SQR] = GDBITS3(9,10,11), + [GTE_DCPL] = GCBITS3(21,22,23) | GDBITS7(6,8,9,10,11,21,22), + [GTE_DPCT] = GCBITS3(21,22,23) | GDBITS4(8,20,21,22), + [GTE_AVSZ3] = GCBIT(29) | GDBITS3(17,18,19), + [GTE_AVSZ4] = GCBIT(30) | GDBITS4(16,17,18,19), + [GTE_RTPT] = 0x1f0000ff00000000ll | GDBITS7(0,1,2,3,4,5,19), + [GTE_GPF] = GDBITS7(6,8,9,10,11,21,22), + [GTE_GPL] = GDBITS10(6,8,9,10,11,21,22,25,26,27), + [GTE_NCCT] = 0x001fff0000000000ll | GDBITS7(0,1,2,3,4,5,6), +}; + +// note: this excludes gteFLAG that is always written to +const uint64_t gte_reg_writes[64] = { + [GTE_RTPS] = 0x0f0f7f00ll, + [GTE_NCLIP] = GDBIT(24), + [GTE_OP] = GDBITS6(9,10,11,25,26,27), + [GTE_DPCS] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_INTPL] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_MVMVA] = GDBITS6(9,10,11,25,26,27), + [GTE_NCDS] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_CDP] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_NCDT] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_NCCS] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_CC] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_NCS] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_NCT] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_SQR] = GDBITS6(9,10,11,25,26,27), + [GTE_DCPL] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_DPCT] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_AVSZ3] = GDBITS2(7,24), + [GTE_AVSZ4] = GDBITS2(7,24), + [GTE_RTPT] = 0x0f0f7f00ll, + [GTE_GPF] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_GPL] = GDBITS9(9,10,11,20,21,22,25,26,27), + [GTE_NCCT] = GDBITS9(9,10,11,20,21,22,25,26,27), +}; + +static int ari64_init() +{ + extern void (*psxCP2[64])(); + extern void psxNULL(); + extern unsigned char *out; + size_t i; + + new_dynarec_init(); + new_dyna_pcsx_mem_init(); + + for (i = 0; i < ARRAY_SIZE(gte_handlers); i++) + if (psxCP2[i] != psxNULL) + gte_handlers[i] = psxCP2[i]; + +#if defined(__arm__) && !defined(DRC_DBG) + gte_handlers[0x06] = gteNCLIP_arm; +#ifdef HAVE_ARMV5 + gte_handlers_nf[0x01] = gteRTPS_nf_arm; + gte_handlers_nf[0x30] = gteRTPT_nf_arm; +#endif +#ifdef __ARM_NEON__ + // compiler's _nf version is still a lot slower than neon + // _nf_arm RTPS is roughly the same, RTPT slower + gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon; + gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon; +#endif +#endif +#ifdef DRC_DBG + memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf)); +#endif + psxH_ptr = psxH; + zeromem_ptr = zero_mem; + scratch_buf_ptr = scratch_buf; + + SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n"); + SysPrintf("%08x/%08x/%08x/%08x/%08x\n", + psxM, psxH, psxR, mem_rtab, out); + + return 0; +} + +static void ari64_reset() +{ + printf("ari64_reset\n"); + new_dyna_pcsx_mem_reset(); + invalidate_all_pages(); + new_dyna_restore(); + pending_exception = 1; +} + +// execute until predefined leave points +// (HLE softcall exit and BIOS fastboot end) +static void ari64_execute_until() +{ + schedule_timeslice(); + + evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc, + psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle); + + new_dyna_start(); + + evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc, + psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle); +} + +static void ari64_execute() +{ + while (!stop) { + ari64_execute_until(); + evprintf("drc left @%08x\n", psxRegs.pc); + } +} + +static void ari64_clear(u32 addr, u32 size) +{ + u32 start, end, main_ram; + + size *= 4; /* PCSX uses DMA units (words) */ + + evprintf("ari64_clear %08x %04x\n", addr, size); + + /* check for RAM mirrors */ + main_ram = (addr & 0xffe00000) == 0x80000000; + + start = addr >> 12; + end = (addr + size) >> 12; + + for (; start <= end; start++) + if (!main_ram || !invalid_code[start]) + invalidate_block(start); +} + +static void ari64_shutdown() +{ + new_dynarec_cleanup(); + new_dyna_pcsx_mem_shutdown(); +} + +extern void intExecute(); +extern void intExecuteT(); +extern void intExecuteBlock(); +extern void intExecuteBlockT(); +#ifndef DRC_DBG +#define intExecuteT intExecute +#define intExecuteBlockT intExecuteBlock +#endif + +R3000Acpu psxRec = { + ari64_init, + ari64_reset, +#ifndef DRC_DISABLE + ari64_execute, + ari64_execute_until, +#else + intExecuteT, + intExecuteBlockT, +#endif + ari64_clear, + ari64_shutdown +}; + +// TODO: rm +#ifndef DRC_DBG +void do_insn_trace() {} +void do_insn_cmp() {} +#endif + +#ifdef DRC_DISABLE +unsigned int address; +int pending_exception, stop; +u32 next_interupt; +int new_dynarec_did_compile; +int cycle_multiplier; +int new_dynarec_hacks; +void *psxH_ptr; +void *zeromem_ptr; +u8 zero_mem[0x1000]; +unsigned char *out; +void *mem_rtab; +void *scratch_buf_ptr; +void new_dynarec_init() { (void)ari64_execute; } +void new_dyna_start() {} +void new_dynarec_cleanup() {} +void new_dynarec_clear_full() {} +void invalidate_all_pages() {} +void invalidate_block(unsigned int block) {} +void new_dyna_pcsx_mem_init(void) {} +void new_dyna_pcsx_mem_reset(void) {} +void new_dyna_pcsx_mem_load_state(void) {} +void new_dyna_pcsx_mem_shutdown(void) {} +int new_dynarec_save_blocks(void *save, int size) { return 0; } +void new_dynarec_load_blocks(const void *save, int size) {} +#endif + +#ifdef DRC_DBG + +#include <stddef.h> +static FILE *f; +extern u32 last_io_addr; + +static void dump_mem(const char *fname, void *mem, size_t size) +{ + FILE *f1 = fopen(fname, "wb"); + if (f1 == NULL) + f1 = fopen(strrchr(fname, '/') + 1, "wb"); + fwrite(mem, 1, size, f1); + fclose(f1); +} + +static u32 memcheck_read(u32 a) +{ + if ((a >> 16) == 0x1f80) + // scratchpad/IO + return *(u32 *)(psxH + (a & 0xfffc)); + + if ((a >> 16) == 0x1f00) + // parallel + return *(u32 *)(psxP + (a & 0xfffc)); + +// if ((a & ~0xe0600000) < 0x200000) + // RAM + return *(u32 *)(psxM + (a & 0x1ffffc)); +} + +void do_insn_trace(void) +{ + static psxRegisters oldregs; + static u32 old_io_addr = (u32)-1; + static u32 old_io_data = 0xbad0c0de; + static u32 event_cycles_o[PSXINT_COUNT]; + u32 *allregs_p = (void *)&psxRegs; + u32 *allregs_o = (void *)&oldregs; + u32 io_data; + int i; + u8 byte; + + //last_io_addr = 0x5e2c8; + if (f == NULL) + f = fopen("tracelog", "wb"); + + // log reg changes + oldregs.code = psxRegs.code; // don't care + for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) { + if (allregs_p[i] != allregs_o[i]) { + fwrite(&i, 1, 1, f); + fwrite(&allregs_p[i], 1, 4, f); + allregs_o[i] = allregs_p[i]; + } + } + // log event changes + for (i = 0; i < PSXINT_COUNT; i++) { + if (event_cycles[i] != event_cycles_o[i]) { + byte = 0xfc; + fwrite(&byte, 1, 1, f); + fwrite(&i, 1, 1, f); + fwrite(&event_cycles[i], 1, 4, f); + event_cycles_o[i] = event_cycles[i]; + } + } + // log last io + if (old_io_addr != last_io_addr) { + byte = 0xfd; + fwrite(&byte, 1, 1, f); + fwrite(&last_io_addr, 1, 4, f); + old_io_addr = last_io_addr; + } + io_data = memcheck_read(last_io_addr); + if (old_io_data != io_data) { + byte = 0xfe; + fwrite(&byte, 1, 1, f); + fwrite(&io_data, 1, 4, f); + old_io_data = io_data; + } + byte = 0xff; + fwrite(&byte, 1, 1, f); + +#if 0 + if (psxRegs.cycle == 190230) { + dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000); + dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000); + printf("dumped\n"); + exit(1); + } +#endif +} + +static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "lo", "hi", + "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7", + "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15", + "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23", + "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31", + + "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7", + "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15", + "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23", + "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31", + + "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7", + "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15", + "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23", + "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31", + + "PC", "code", "cycle", "interrupt", +}; + +static struct { + int reg; + u32 val, val_expect; + u32 pc, cycle; +} miss_log[64]; +static int miss_log_i; +#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0])) +#define miss_log_mask (miss_log_len-1) + +static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle) +{ + miss_log[miss_log_i].reg = reg; + miss_log[miss_log_i].val = val; + miss_log[miss_log_i].val_expect = val_expect; + miss_log[miss_log_i].pc = pc; + miss_log[miss_log_i].cycle = cycle; + miss_log_i = (miss_log_i + 1) & miss_log_mask; +} + +void breakme() {} + +void do_insn_cmp(void) +{ + static psxRegisters rregs; + static u32 mem_addr, mem_val; + u32 *allregs_p = (void *)&psxRegs; + u32 *allregs_e = (void *)&rregs; + static u32 ppc, failcount; + int i, ret, bad = 0, which_event = -1; + u32 ev_cycles = 0; + u8 code; + + if (f == NULL) + f = fopen("tracelog", "rb"); + + while (1) { + if ((ret = fread(&code, 1, 1, f)) <= 0) + break; + if (ret <= 0) + break; + if (code == 0xff) + break; + switch (code) { + case 0xfc: + which_event = 0; + fread(&which_event, 1, 1, f); + fread(&ev_cycles, 1, 4, f); + continue; + case 0xfd: + fread(&mem_addr, 1, 4, f); + continue; + case 0xfe: + fread(&mem_val, 1, 4, f); + continue; + } + fread(&allregs_e[code], 1, 4, f); + } + + if (ret <= 0) { + printf("EOF?\n"); + goto end; + } + + psxRegs.code = rregs.code; // don't care + psxRegs.cycle = rregs.cycle; + psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count + + //if (psxRegs.cycle == 166172) breakme(); + + if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 && + mem_val == memcheck_read(mem_addr) + ) { + failcount = 0; + goto ok; + } + + for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) { + if (allregs_p[i] != allregs_e[i]) { + miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle); + bad++; + } + } + + if (mem_val != memcheck_read(mem_addr)) { + printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val); + goto end; + } + + if (which_event >= 0 && event_cycles[which_event] != ev_cycles) { + printf("bad ev_cycles #%d: %08x %08x\n", which_event, event_cycles[which_event], ev_cycles); + goto end; + } + + if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) { + static int last_mcycle; + if (last_mcycle != psxRegs.cycle >> 20) { + printf("%u\n", psxRegs.cycle); + last_mcycle = psxRegs.cycle >> 20; + } + failcount++; + goto ok; + } + +end: + for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask) + printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n", + regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val, + miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle); + printf("-- %d\n", bad); + for (i = 0; i < 8; i++) + printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i], + i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]); + printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle); + dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000); + dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000); + exit(1); +ok: + psxRegs.cycle = rregs.cycle + 2; // sync timing + ppc = psxRegs.pc; +} + +#endif diff --git a/libpcsxcore/new_dynarec/backends/psx/emu_if.h b/libpcsxcore/new_dynarec/backends/psx/emu_if.h new file mode 100644 index 0000000..d8c7990 --- /dev/null +++ b/libpcsxcore/new_dynarec/backends/psx/emu_if.h @@ -0,0 +1,108 @@ +#include "../../new_dynarec.h" +#include "../../../r3000a.h" + +extern char invalid_code[0x100000]; + +/* weird stuff */ +#define EAX 0 +#define ECX 1 + +/* same as psxRegs */ +extern int reg[]; + +/* same as psxRegs.GPR.n.* */ +extern int hi, lo; + +/* same as psxRegs.CP0.n.* */ +extern int reg_cop0[]; +#define Status psxRegs.CP0.n.Status +#define Cause psxRegs.CP0.n.Cause +#define EPC psxRegs.CP0.n.EPC +#define BadVAddr psxRegs.CP0.n.BadVAddr +#define Context psxRegs.CP0.n.Context +#define EntryHi psxRegs.CP0.n.EntryHi +#define Count psxRegs.cycle // psxRegs.CP0.n.Count + +/* COP2/GTE */ +enum gte_opcodes { + GTE_RTPS = 0x01, + GTE_NCLIP = 0x06, + GTE_OP = 0x0c, + GTE_DPCS = 0x10, + GTE_INTPL = 0x11, + GTE_MVMVA = 0x12, + GTE_NCDS = 0x13, + GTE_CDP = 0x14, + GTE_NCDT = 0x16, + GTE_NCCS = 0x1b, + GTE_CC = 0x1c, + GTE_NCS = 0x1e, + GTE_NCT = 0x20, + GTE_SQR = 0x28, + GTE_DCPL = 0x29, + GTE_DPCT = 0x2a, + GTE_AVSZ3 = 0x2d, + GTE_AVSZ4 = 0x2e, + GTE_RTPT = 0x30, + GTE_GPF = 0x3d, + GTE_GPL = 0x3e, + GTE_NCCT = 0x3f, +}; + +extern int reg_cop2d[], reg_cop2c[]; +extern void *gte_handlers[64]; +extern void *gte_handlers_nf[64]; +extern const char *gte_regnames[64]; +extern const char gte_cycletab[64]; +extern const uint64_t gte_reg_reads[64]; +extern const uint64_t gte_reg_writes[64]; + +/* dummy */ +extern int FCR0, FCR31; + +/* mem */ +extern void *mem_rtab; +extern void *mem_wtab; + +void jump_handler_read8(u32 addr, u32 *table, u32 cycles); +void jump_handler_read16(u32 addr, u32 *table, u32 cycles); +void jump_handler_read32(u32 addr, u32 *table, u32 cycles); +void jump_handler_write8(u32 addr, u32 data, u32 cycles, u32 *table); +void jump_handler_write16(u32 addr, u32 data, u32 cycles, u32 *table); +void jump_handler_write32(u32 addr, u32 data, u32 cycles, u32 *table); +void jump_handler_write_h(u32 addr, u32 data, u32 cycles, void *handler); +void jump_handle_swl(u32 addr, u32 data, u32 cycles); +void jump_handle_swr(u32 addr, u32 data, u32 cycles); +void rcnt0_read_count_m0(u32 addr, u32, u32 cycles); +void rcnt0_read_count_m1(u32 addr, u32, u32 cycles); +void rcnt1_read_count_m0(u32 addr, u32, u32 cycles); +void rcnt1_read_count_m1(u32 addr, u32, u32 cycles); +void rcnt2_read_count_m0(u32 addr, u32, u32 cycles); +void rcnt2_read_count_m1(u32 addr, u32, u32 cycles); + +extern unsigned int address; +extern void *psxH_ptr; +extern void *zeromem_ptr; +extern void *scratch_buf_ptr; + +// same as invalid_code, just a region for ram write checks (inclusive) +extern u32 inv_code_start, inv_code_end; + +/* cycles/irqs */ +extern u32 next_interupt; +extern int pending_exception; + +/* called by drc */ +void pcsx_mtc0(u32 reg, u32 val); +void pcsx_mtc0_ds(u32 reg, u32 val); + +/* misc */ +extern void (*psxHLEt[])(); + +extern void SysPrintf(const char *fmt, ...); + +#ifdef RAM_FIXED +#define rdram ((u_int)0x80000000) +#else +#define rdram ((u_int)psxM) +#endif diff --git a/libpcsxcore/new_dynarec/backends/psx/pcsxmem.c b/libpcsxcore/new_dynarec/backends/psx/pcsxmem.c new file mode 100644 index 0000000..647981e --- /dev/null +++ b/libpcsxcore/new_dynarec/backends/psx/pcsxmem.c @@ -0,0 +1,494 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2010-2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <stdio.h> +#include "../../../psxhw.h" +#include "../../../cdrom.h" +#include "../../../mdec.h" +#include "../../../gpu.h" +#include "../../../psxmem_map.h" +#include "emu_if.h" +#include "pcsxmem.h" + +#ifdef __thumb__ +#error the dynarec is incompatible with Thumb functions, +#error please add -marm to compile flags +#endif + +//#define memprintf printf +#define memprintf(...) + +static u32 *mem_readtab; +static u32 *mem_writetab; +static u32 mem_iortab[(1+2+4) * 0x1000 / 4]; +static u32 mem_iowtab[(1+2+4) * 0x1000 / 4]; +static u32 mem_ffwtab[(1+2+4) * 0x1000 / 4]; +//static u32 mem_unmrtab[(1+2+4) * 0x1000 / 4]; +static u32 mem_unmwtab[(1+2+4) * 0x1000 / 4]; + +// When this is called in a loop, and 'h' is a function pointer, clang will crash. +#ifdef __clang__ +static __attribute__ ((noinline)) void map_item(u32 *out, const void *h, u32 flag) +#else +static void map_item(u32 *out, const void *h, u32 flag) +#endif +{ + u32 hv = (u32)h; + if (hv & 1) { + SysPrintf("FATAL: %p has LSB set\n", h); + abort(); + } + *out = (hv >> 1) | (flag << 31); +} + +// size must be power of 2, at least 4k +#define map_l1_mem(tab, i, addr, size, base) \ + map_item(&tab[((addr)>>12) + i], (u8 *)(base) - (u32)(addr) - ((i << 12) & ~(size - 1)), 0) + +#define IOMEM32(a) (((a) & 0xfff) / 4) +#define IOMEM16(a) (0x1000/4 + (((a) & 0xfff) / 2)) +#define IOMEM8(a) (0x1000/4 + 0x1000/2 + ((a) & 0xfff)) + +u8 zero_mem[0x1000]; + +u32 read_mem_dummy() +{ + return 0; +} + +static void write_mem_dummy(u32 data) +{ + memprintf("unmapped w %08x, %08x @%08x %u\n", address, data, psxRegs.pc, psxRegs.cycle); +} + +/* IO handlers */ +static u32 io_read_sio16() +{ + return sioRead8() | (sioRead8() << 8); +} + +static u32 io_read_sio32() +{ + return sioRead8() | (sioRead8() << 8) | (sioRead8() << 16) | (sioRead8() << 24); +} + +static void io_write_sio16(u32 value) +{ + sioWrite8((unsigned char)value); + sioWrite8((unsigned char)(value>>8)); +} + +static void io_write_sio32(u32 value) +{ + sioWrite8((unsigned char)value); + sioWrite8((unsigned char)(value >> 8)); + sioWrite8((unsigned char)(value >> 16)); + sioWrite8((unsigned char)(value >> 24)); +} + +#ifndef DRC_DBG + +static void map_rcnt_rcount0(u32 mode) +{ + if (mode & 0x100) { // pixel clock + map_item(&mem_iortab[IOMEM32(0x1100)], rcnt0_read_count_m1, 1); + map_item(&mem_iortab[IOMEM16(0x1100)], rcnt0_read_count_m1, 1); + } + else { + map_item(&mem_iortab[IOMEM32(0x1100)], rcnt0_read_count_m0, 1); + map_item(&mem_iortab[IOMEM16(0x1100)], rcnt0_read_count_m0, 1); + } +} + +static void map_rcnt_rcount1(u32 mode) +{ + if (mode & 0x100) { // hcnt + map_item(&mem_iortab[IOMEM32(0x1110)], rcnt1_read_count_m1, 1); + map_item(&mem_iortab[IOMEM16(0x1110)], rcnt1_read_count_m1, 1); + } + else { + map_item(&mem_iortab[IOMEM32(0x1110)], rcnt1_read_count_m0, 1); + map_item(&mem_iortab[IOMEM16(0x1110)], rcnt1_read_count_m0, 1); + } +} + +static void map_rcnt_rcount2(u32 mode) +{ + if (mode & 0x01) { // gate + map_item(&mem_iortab[IOMEM32(0x1120)], &psxH[0x1000], 0); + map_item(&mem_iortab[IOMEM16(0x1120)], &psxH[0x1000], 0); + } + else if (mode & 0x200) { // clk/8 + map_item(&mem_iortab[IOMEM32(0x1120)], rcnt2_read_count_m1, 1); + map_item(&mem_iortab[IOMEM16(0x1120)], rcnt2_read_count_m1, 1); + } + else { + map_item(&mem_iortab[IOMEM32(0x1120)], rcnt2_read_count_m0, 1); + map_item(&mem_iortab[IOMEM16(0x1120)], rcnt2_read_count_m0, 1); + } +} + +#else +#define map_rcnt_rcount0(mode) +#define map_rcnt_rcount1(mode) +#define map_rcnt_rcount2(mode) +#endif + +#define make_rcnt_funcs(i) \ +static u32 io_rcnt_read_count##i() { return psxRcntRcount(i); } \ +static u32 io_rcnt_read_mode##i() { return psxRcntRmode(i); } \ +static u32 io_rcnt_read_target##i() { return psxRcntRtarget(i); } \ +static void io_rcnt_write_count##i(u32 val) { psxRcntWcount(i, val & 0xffff); } \ +static void io_rcnt_write_mode##i(u32 val) { psxRcntWmode(i, val); map_rcnt_rcount##i(val); } \ +static void io_rcnt_write_target##i(u32 val) { psxRcntWtarget(i, val & 0xffff); } + +make_rcnt_funcs(0) +make_rcnt_funcs(1) +make_rcnt_funcs(2) + +static void io_write_ireg16(u32 value) +{ + //if (Config.Sio) psxHu16ref(0x1070) |= 0x80; + if (Config.SpuIrq) psxHu16ref(0x1070) |= 0x200; + psxHu16ref(0x1070) &= value; +} + +static void io_write_imask16(u32 value) +{ + psxHu16ref(0x1074) = value; + if (psxHu16ref(0x1070) & value) + new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1); +} + +static void io_write_ireg32(u32 value) +{ + //if (Config.Sio) psxHu32ref(0x1070) |= 0x80; + if (Config.SpuIrq) psxHu32ref(0x1070) |= 0x200; + psxHu32ref(0x1070) &= value; +} + +static void io_write_imask32(u32 value) +{ + psxHu32ref(0x1074) = value; + if (psxHu32ref(0x1070) & value) + new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1); +} + +static void io_write_dma_icr32(u32 value) +{ + u32 tmp = value & 0x00ff803f; + tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000; + if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000) + || tmp & HW_DMA_ICR_BUS_ERROR) { + if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT)) + psxHu32ref(0x1070) |= SWAP32(8); + tmp |= HW_DMA_ICR_IRQ_SENT; + } + HW_DMA_ICR = SWAPu32(tmp); +} + +#define make_dma_func(n) \ +static void io_write_chcr##n(u32 value) \ +{ \ + HW_DMA##n##_CHCR = value; \ + if (value & 0x01000000 && HW_DMA_PCR & (8 << (n * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, value); \ + } \ +} + +make_dma_func(0) +make_dma_func(1) +make_dma_func(2) +make_dma_func(3) +make_dma_func(4) +make_dma_func(6) + +static void io_spu_write16(u32 value) +{ + // meh + SPU_writeRegister(address, value, psxRegs.cycle); +} + +static void io_spu_write32(u32 value) +{ + SPUwriteRegister wfunc = SPU_writeRegister; + u32 a = address; + + wfunc(a, value & 0xffff, psxRegs.cycle); + wfunc(a + 2, value >> 16, psxRegs.cycle); +} + +static u32 io_gpu_read_status(void) +{ + u32 v; + + // meh2, syncing for img bit, might want to avoid it.. + gpuSyncPluginSR(); + v = HW_GPU_STATUS; + + // XXX: because of large timeslices can't use hSyncCount, using rough + // approximization instead. Perhaps better use hcounter code here or something. + if (hSyncCount < 240 && (HW_GPU_STATUS & PSXGPU_ILACE_BITS) != PSXGPU_ILACE_BITS) + v |= PSXGPU_LCF & (psxRegs.cycle << 20); + return v; +} + +static void io_gpu_write_status(u32 value) +{ + GPU_writeStatus(value); + gpuSyncPluginSR(); +} + +static void map_ram_write(void) +{ + int i; + + for (i = 0; i < (0x800000 >> 12); i++) { + map_l1_mem(mem_writetab, i, 0x80000000, 0x200000, psxM); + map_l1_mem(mem_writetab, i, 0x00000000, 0x200000, psxM); + map_l1_mem(mem_writetab, i, 0xa0000000, 0x200000, psxM); + } +} + +static void unmap_ram_write(void) +{ + int i; + + for (i = 0; i < (0x800000 >> 12); i++) { + map_item(&mem_writetab[0x80000|i], mem_unmwtab, 1); + map_item(&mem_writetab[0x00000|i], mem_unmwtab, 1); + map_item(&mem_writetab[0xa0000|i], mem_unmwtab, 1); + } +} + +static void write_biu(u32 value) +{ + memprintf("write_biu %08x, %08x @%08x %u\n", address, value, psxRegs.pc, psxRegs.cycle); + + if (address != 0xfffe0130) + return; + + switch (value) { + case 0x800: case 0x804: + unmap_ram_write(); + break; + case 0: case 0x1e988: + map_ram_write(); + break; + default: + printf("write_biu: unexpected val: %08x\n", value); + break; + } +} + +void new_dyna_pcsx_mem_load_state(void) +{ + map_rcnt_rcount0(rcnts[0].mode); + map_rcnt_rcount1(rcnts[1].mode); + map_rcnt_rcount2(rcnts[2].mode); +} + +int pcsxmem_is_handler_dynamic(unsigned int addr) +{ + if ((addr & 0xfffff000) != 0x1f801000) + return 0; + + addr &= 0xffff; + return addr == 0x1100 || addr == 0x1110 || addr == 0x1120; +} + +void new_dyna_pcsx_mem_init(void) +{ + int i; + + // have to map these further to keep tcache close to .text + mem_readtab = psxMap(0x08000000, 0x200000 * 4, 0, MAP_TAG_LUTS); + if (mem_readtab == NULL) { + SysPrintf("failed to map mem tables\n"); + exit(1); + } + mem_writetab = mem_readtab + 0x100000; + + // 1st level lookup: + // 0: direct mem + // 1: use 2nd lookup + // 2nd level lookup: + // 0: direct mem variable + // 1: memhandler + + // default/unmapped memhandlers + for (i = 0; i < 0x100000; i++) { + //map_item(&mem_readtab[i], mem_unmrtab, 1); + map_l1_mem(mem_readtab, i, 0, 0x1000, zero_mem); + map_item(&mem_writetab[i], mem_unmwtab, 1); + } + + // RAM and it's mirrors + for (i = 0; i < (0x800000 >> 12); i++) { + map_l1_mem(mem_readtab, i, 0x80000000, 0x200000, psxM); + map_l1_mem(mem_readtab, i, 0x00000000, 0x200000, psxM); + map_l1_mem(mem_readtab, i, 0xa0000000, 0x200000, psxM); + } + map_ram_write(); + + // BIOS and it's mirrors + for (i = 0; i < (0x80000 >> 12); i++) { + map_l1_mem(mem_readtab, i, 0x1fc00000, 0x80000, psxR); + map_l1_mem(mem_readtab, i, 0xbfc00000, 0x80000, psxR); + } + + // scratchpad + map_l1_mem(mem_readtab, 0, 0x1f800000, 0x1000, psxH); + map_l1_mem(mem_readtab, 0, 0x9f800000, 0x1000, psxH); + map_l1_mem(mem_writetab, 0, 0x1f800000, 0x1000, psxH); + map_l1_mem(mem_writetab, 0, 0x9f800000, 0x1000, psxH); + + // I/O + map_item(&mem_readtab[0x1f801000 >> 12], mem_iortab, 1); + map_item(&mem_readtab[0x9f801000 >> 12], mem_iortab, 1); + map_item(&mem_readtab[0xbf801000 >> 12], mem_iortab, 1); + map_item(&mem_writetab[0x1f801000 >> 12], mem_iowtab, 1); + map_item(&mem_writetab[0x9f801000 >> 12], mem_iowtab, 1); + map_item(&mem_writetab[0xbf801000 >> 12], mem_iowtab, 1); + + // L2 + // unmapped tables + for (i = 0; i < (1+2+4) * 0x1000 / 4; i++) + map_item(&mem_unmwtab[i], write_mem_dummy, 1); + + // fill IO tables + for (i = 0; i < 0x1000/4; i++) { + map_item(&mem_iortab[i], &psxH[0x1000], 0); + map_item(&mem_iowtab[i], &psxH[0x1000], 0); + } + for (; i < 0x1000/4 + 0x1000/2; i++) { + map_item(&mem_iortab[i], &psxH[0x1000], 0); + map_item(&mem_iowtab[i], &psxH[0x1000], 0); + } + for (; i < 0x1000/4 + 0x1000/2 + 0x1000; i++) { + map_item(&mem_iortab[i], &psxH[0x1000], 0); + map_item(&mem_iowtab[i], &psxH[0x1000], 0); + } + + map_item(&mem_iortab[IOMEM32(0x1040)], io_read_sio32, 1); + map_item(&mem_iortab[IOMEM32(0x1100)], io_rcnt_read_count0, 1); + map_item(&mem_iortab[IOMEM32(0x1104)], io_rcnt_read_mode0, 1); + map_item(&mem_iortab[IOMEM32(0x1108)], io_rcnt_read_target0, 1); + map_item(&mem_iortab[IOMEM32(0x1110)], io_rcnt_read_count1, 1); + map_item(&mem_iortab[IOMEM32(0x1114)], io_rcnt_read_mode1, 1); + map_item(&mem_iortab[IOMEM32(0x1118)], io_rcnt_read_target1, 1); + map_item(&mem_iortab[IOMEM32(0x1120)], io_rcnt_read_count2, 1); + map_item(&mem_iortab[IOMEM32(0x1124)], io_rcnt_read_mode2, 1); + map_item(&mem_iortab[IOMEM32(0x1128)], io_rcnt_read_target2, 1); +// map_item(&mem_iortab[IOMEM32(0x1810)], GPU_readData, 1); + map_item(&mem_iortab[IOMEM32(0x1814)], io_gpu_read_status, 1); + map_item(&mem_iortab[IOMEM32(0x1820)], mdecRead0, 1); + map_item(&mem_iortab[IOMEM32(0x1824)], mdecRead1, 1); + + map_item(&mem_iortab[IOMEM16(0x1040)], io_read_sio16, 1); + map_item(&mem_iortab[IOMEM16(0x1044)], sioReadStat16, 1); + map_item(&mem_iortab[IOMEM16(0x1048)], sioReadMode16, 1); + map_item(&mem_iortab[IOMEM16(0x104a)], sioReadCtrl16, 1); + map_item(&mem_iortab[IOMEM16(0x104e)], sioReadBaud16, 1); + map_item(&mem_iortab[IOMEM16(0x1100)], io_rcnt_read_count0, 1); + map_item(&mem_iortab[IOMEM16(0x1104)], io_rcnt_read_mode0, 1); + map_item(&mem_iortab[IOMEM16(0x1108)], io_rcnt_read_target0, 1); + map_item(&mem_iortab[IOMEM16(0x1110)], io_rcnt_read_count1, 1); + map_item(&mem_iortab[IOMEM16(0x1114)], io_rcnt_read_mode1, 1); + map_item(&mem_iortab[IOMEM16(0x1118)], io_rcnt_read_target1, 1); + map_item(&mem_iortab[IOMEM16(0x1120)], io_rcnt_read_count2, 1); + map_item(&mem_iortab[IOMEM16(0x1124)], io_rcnt_read_mode2, 1); + map_item(&mem_iortab[IOMEM16(0x1128)], io_rcnt_read_target2, 1); + + map_item(&mem_iortab[IOMEM8(0x1040)], sioRead8, 1); + map_item(&mem_iortab[IOMEM8(0x1800)], cdrRead0, 1); + map_item(&mem_iortab[IOMEM8(0x1801)], cdrRead1, 1); + map_item(&mem_iortab[IOMEM8(0x1802)], cdrRead2, 1); + map_item(&mem_iortab[IOMEM8(0x1803)], cdrRead3, 1); + + // write(u32 data) + map_item(&mem_iowtab[IOMEM32(0x1040)], io_write_sio32, 1); + map_item(&mem_iowtab[IOMEM32(0x1070)], io_write_ireg32, 1); + map_item(&mem_iowtab[IOMEM32(0x1074)], io_write_imask32, 1); + map_item(&mem_iowtab[IOMEM32(0x1088)], io_write_chcr0, 1); + map_item(&mem_iowtab[IOMEM32(0x1098)], io_write_chcr1, 1); + map_item(&mem_iowtab[IOMEM32(0x10a8)], io_write_chcr2, 1); + map_item(&mem_iowtab[IOMEM32(0x10b8)], io_write_chcr3, 1); + map_item(&mem_iowtab[IOMEM32(0x10c8)], io_write_chcr4, 1); + map_item(&mem_iowtab[IOMEM32(0x10e8)], io_write_chcr6, 1); + map_item(&mem_iowtab[IOMEM32(0x10f4)], io_write_dma_icr32, 1); + map_item(&mem_iowtab[IOMEM32(0x1100)], io_rcnt_write_count0, 1); + map_item(&mem_iowtab[IOMEM32(0x1104)], io_rcnt_write_mode0, 1); + map_item(&mem_iowtab[IOMEM32(0x1108)], io_rcnt_write_target0, 1); + map_item(&mem_iowtab[IOMEM32(0x1110)], io_rcnt_write_count1, 1); + map_item(&mem_iowtab[IOMEM32(0x1114)], io_rcnt_write_mode1, 1); + map_item(&mem_iowtab[IOMEM32(0x1118)], io_rcnt_write_target1, 1); + map_item(&mem_iowtab[IOMEM32(0x1120)], io_rcnt_write_count2, 1); + map_item(&mem_iowtab[IOMEM32(0x1124)], io_rcnt_write_mode2, 1); + map_item(&mem_iowtab[IOMEM32(0x1128)], io_rcnt_write_target2, 1); +// map_item(&mem_iowtab[IOMEM32(0x1810)], GPU_writeData, 1); + map_item(&mem_iowtab[IOMEM32(0x1814)], io_gpu_write_status, 1); + map_item(&mem_iowtab[IOMEM32(0x1820)], mdecWrite0, 1); + map_item(&mem_iowtab[IOMEM32(0x1824)], mdecWrite1, 1); + + map_item(&mem_iowtab[IOMEM16(0x1040)], io_write_sio16, 1); + map_item(&mem_iowtab[IOMEM16(0x1044)], sioWriteStat16, 1); + map_item(&mem_iowtab[IOMEM16(0x1048)], sioWriteMode16, 1); + map_item(&mem_iowtab[IOMEM16(0x104a)], sioWriteCtrl16, 1); + map_item(&mem_iowtab[IOMEM16(0x104e)], sioWriteBaud16, 1); + map_item(&mem_iowtab[IOMEM16(0x1070)], io_write_ireg16, 1); + map_item(&mem_iowtab[IOMEM16(0x1074)], io_write_imask16, 1); + map_item(&mem_iowtab[IOMEM16(0x1100)], io_rcnt_write_count0, 1); + map_item(&mem_iowtab[IOMEM16(0x1104)], io_rcnt_write_mode0, 1); + map_item(&mem_iowtab[IOMEM16(0x1108)], io_rcnt_write_target0, 1); + map_item(&mem_iowtab[IOMEM16(0x1110)], io_rcnt_write_count1, 1); + map_item(&mem_iowtab[IOMEM16(0x1114)], io_rcnt_write_mode1, 1); + map_item(&mem_iowtab[IOMEM16(0x1118)], io_rcnt_write_target1, 1); + map_item(&mem_iowtab[IOMEM16(0x1120)], io_rcnt_write_count2, 1); + map_item(&mem_iowtab[IOMEM16(0x1124)], io_rcnt_write_mode2, 1); + map_item(&mem_iowtab[IOMEM16(0x1128)], io_rcnt_write_target2, 1); + + map_item(&mem_iowtab[IOMEM8(0x1040)], sioWrite8, 1); + map_item(&mem_iowtab[IOMEM8(0x1800)], cdrWrite0, 1); + map_item(&mem_iowtab[IOMEM8(0x1801)], cdrWrite1, 1); + map_item(&mem_iowtab[IOMEM8(0x1802)], cdrWrite2, 1); + map_item(&mem_iowtab[IOMEM8(0x1803)], cdrWrite3, 1); + + for (i = 0x1c00; i < 0x1e00; i += 2) { + map_item(&mem_iowtab[IOMEM16(i)], io_spu_write16, 1); + map_item(&mem_iowtab[IOMEM32(i)], io_spu_write32, 1); + } + + // misc + map_item(&mem_writetab[0xfffe0130 >> 12], mem_ffwtab, 1); + for (i = 0; i < 0x1000/4 + 0x1000/2 + 0x1000; i++) + map_item(&mem_ffwtab[i], write_biu, 1); + + mem_rtab = mem_readtab; + mem_wtab = mem_writetab; + + new_dyna_pcsx_mem_load_state(); +} + +void new_dyna_pcsx_mem_reset(void) +{ + int i; + + // plugins might change so update the pointers + map_item(&mem_iortab[IOMEM32(0x1810)], GPU_readData, 1); + + for (i = 0x1c00; i < 0x1e00; i += 2) + map_item(&mem_iortab[IOMEM16(i)], SPU_readRegister, 1); + + map_item(&mem_iowtab[IOMEM32(0x1810)], GPU_writeData, 1); +} + +void new_dyna_pcsx_mem_shutdown(void) +{ + psxUnmap(mem_readtab, 0x200000 * 4, MAP_TAG_LUTS); + mem_writetab = mem_readtab = NULL; +} diff --git a/libpcsxcore/new_dynarec/backends/psx/pcsxmem.h b/libpcsxcore/new_dynarec/backends/psx/pcsxmem.h new file mode 100644 index 0000000..72892a8 --- /dev/null +++ b/libpcsxcore/new_dynarec/backends/psx/pcsxmem.h @@ -0,0 +1,9 @@ + +extern u8 zero_mem[0x1000]; + +void new_dyna_pcsx_mem_init(void); +void new_dyna_pcsx_mem_reset(void); +void new_dyna_pcsx_mem_load_state(void); +void new_dyna_pcsx_mem_shutdown(void); + +int pcsxmem_is_handler_dynamic(unsigned int addr); diff --git a/libpcsxcore/new_dynarec/backends/psx/pcsxmem_inline.c b/libpcsxcore/new_dynarec/backends/psx/pcsxmem_inline.c new file mode 100644 index 0000000..305931a --- /dev/null +++ b/libpcsxcore/new_dynarec/backends/psx/pcsxmem_inline.c @@ -0,0 +1,66 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef DRC_DBG + +static int pcsx_direct_read(int type, u_int addr, int cc_adj, int cc, int rs, int rt) +{ + if ((addr & 0xfffff000) == 0x1f801000) { + u_int t; + switch (addr & 0xffff) { + case 0x1120: // rcnt2 count + if (rt < 0) goto dont_care; + if (cc < 0) return 0; + emit_readword((int)&rcnts[2].mode, HOST_TEMPREG); + emit_readword((int)&rcnts[2].cycleStart, rt); + emit_testimm(HOST_TEMPREG, 0x200); + emit_readword((int)&last_count, HOST_TEMPREG); + emit_sub(HOST_TEMPREG, rt, HOST_TEMPREG); + emit_add(HOST_TEMPREG, cc, HOST_TEMPREG); + if (cc_adj) + emit_addimm(HOST_TEMPREG, cc_adj, rt); + emit_shrne_imm(rt, 3, rt); + mov_loadtype_adj(type!=LOADW_STUB?type:LOADH_STUB, rt, rt); + goto hit; + case 0x1104: + case 0x1114: + case 0x1124: // rcnt mode + if (rt < 0) return 0; + t = (addr >> 4) & 3; + emit_readword((int)&rcnts[t].mode, rt); + emit_andimm(rt, ~0x1800, HOST_TEMPREG); + emit_writeword(HOST_TEMPREG, (int)&rcnts[t].mode); + mov_loadtype_adj(type, rt, rt); + goto hit; + } + } + else { + if (rt < 0) + goto dont_care; + } + + return 0; + +hit: + assem_debug("pcsx_direct_read %08x end\n", addr); + return 1; + +dont_care: + assem_debug("pcsx_direct_read %08x dummy\n", addr); + return 1; +} + +#else + +static int pcsx_direct_read(int type, u_int addr, int cc_adj, int cc, int rs, int rt) +{ + return 0; +} + +#endif + +// vim:shiftwidth=2:expandtab |