From: notaz Date: Sat, 14 Feb 2026 00:46:50 +0000 (+0200) Subject: psxmem: reduce lut table size X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dc4be87d9c448416428dc3334d33b434f46c6a7a;p=pcsx_rearmed.git psxmem: reduce lut table size No reason for them to be 64k, unused by the dynarecs anyway and just wastes memory there. Also move to psxRegs for less literal pools on arm. --- diff --git a/frontend/libretro.c b/frontend/libretro.c index a7ad22ed..7f484d52 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -1732,10 +1732,10 @@ static void set_retro_memmap(void) uint64_t flags_ram = RETRO_MEMDESC_SYSTEM_RAM; struct retro_memory_map retromap = { 0 }; struct retro_memory_descriptor descs[] = { - { flags_ram, psxM, 0, 0x00000000, 0x5fe00000, 0, 0x200000 }, - { flags_ram, psxH, 0, 0x1f800000, 0x7ffffc00, 0, 0x000400 }, + { flags_ram, psxRegs.ptrs.psxM, 0, 0x00000000, 0x5fe00000, 0, 0x200000 }, + { flags_ram, psxRegs.ptrs.psxH, 0, 0x1f800000, 0x7ffffc00, 0, 0x000400 }, // not ram but let the frontend patch it if it wants; should be last - { flags_ram, psxR, 0, 0x1fc00000, 0x5ff80000, 0, 0x080000 }, + { flags_ram, psxRegs.ptrs.psxR, 0, 0x1fc00000, 0x5ff80000, 0, 0x080000 }, }; retromap.descriptors = descs; @@ -2091,7 +2091,7 @@ void *retro_get_memory_data(unsigned id) if (id == RETRO_MEMORY_SAVE_RAM) return Mcd1Data; else if (id == RETRO_MEMORY_SYSTEM_RAM) - return psxM; + return psxRegs.ptrs.psxM; else return NULL; } diff --git a/include/compiler_features.h b/include/compiler_features.h index 77114efb..85fc1da1 100644 --- a/include/compiler_features.h +++ b/include/compiler_features.h @@ -1,3 +1,5 @@ +#ifndef PCSX_COMPILER_FEATURES_H_ +#define PCSX_COMPILER_FEATURES_H_ #ifdef __GNUC__ # define likely(x) __builtin_expect((x),1) @@ -9,12 +11,14 @@ # define noinline __attribute__((noinline,noclone)) # endif # define attr_unused __attribute__((unused)) +# define nosanitize(x) __attribute__((no_sanitize(x))) #else # define likely(x) (x) # define unlikely(x) (x) # define preload (x) # define noinline # define attr_unused +# define nosanitize(x) #endif // doesn't work on Android, mingw... @@ -36,3 +40,4 @@ #define sub_overflow(a, b, r) ({r = (u32)a - (u32)b; (a ^ b) & (a ^ r) & (1u<<31);}) #endif +#endif // PCSX_COMPILER_FEATURES_H_ diff --git a/libpcsxcore/cheat.c b/libpcsxcore/cheat.c index 7b81737c..ae5e5c2b 100644 --- a/libpcsxcore/cheat.c +++ b/libpcsxcore/cheat.c @@ -232,7 +232,7 @@ void ApplyCheats() { break; case CHEAT_SCRATCHPAD16: // 1F - psxHs16ref(addr) = SWAPu16(val); + psxHu16ref(addr) = SWAPu16(val); break; case CHEAT_INC16: @@ -513,7 +513,7 @@ void FreeCheatSearchMem() { void CheatSearchBackupMemory() { if (prevM != NULL) { - memcpy(prevM, psxM, 0x200000); + memcpy(prevM, psxRegs.ptrs.psxM, 0x200000); } } diff --git a/libpcsxcore/lightrec/mem.c b/libpcsxcore/lightrec/mem.c index 4b582583..ec628534 100644 --- a/libpcsxcore/lightrec/mem.c +++ b/libpcsxcore/lightrec/mem.c @@ -129,7 +129,7 @@ static int lightrec_mmap_ram(bool hugetlb) } err = 0; - psxM = (s8 *)base; + psxRegs.ptrs.psxM = (u8 *)base; err_close_memfd: close(memfd); @@ -139,7 +139,7 @@ err_close_memfd: int lightrec_init_mmap(void) { unsigned int i; - s8 *base, *target; + u8 *base, *target; void *map; int err = lightrec_mmap_ram(true); if (err) { @@ -150,7 +150,7 @@ int lightrec_init_mmap(void) } } - base = psxM; + base = psxRegs.ptrs.psxM; target = base + 0x1f000000; map = mmap(target, 0x10000, @@ -164,7 +164,7 @@ int lightrec_init_mmap(void) if (map != target) SysMessage("lightrec: mapped parallel port at %p, wanted %p", map, target); - psxP = (s8 *)map; + psxRegs.ptrs.psxP = (u8 *)map; target = base + 0x1fc00000; map = mmap_huge(target, 0x200000, @@ -178,7 +178,7 @@ int lightrec_init_mmap(void) if (map != target) SysMessage("lightrec: mapped bios at %p, wanted %p", map, target); - psxR = (s8 *)map; + psxRegs.ptrs.psxR = (u8 *)map; target = base + 0x1f800000; map = mmap(target, 0x10000, @@ -192,7 +192,7 @@ int lightrec_init_mmap(void) if (map != target) SysMessage("lightrec: mapped scratchpad at %p, wanted %p", map, target); - psxH = (s8 *)map; + psxRegs.ptrs.psxH = (u8 *)map; target = base + 0x800000; map = mmap_huge(target, CODE_BUFFER_SIZE, @@ -212,14 +212,14 @@ int lightrec_init_mmap(void) return 0; err_unmap_scratch: - munmap(psxH, 0x10000); + munmap(psxRegs.ptrs.psxH, 0x10000); err_unmap_bios: - munmap(psxR, 0x200000); + munmap(psxRegs.ptrs.psxR, 0x200000); err_unmap_parallel: - munmap(psxP, 0x10000); + munmap(psxRegs.ptrs.psxP, 0x10000); err_unmap: for (i = 0; i < 4; i++) - munmap((void *)((uintptr_t)psxM + i * 0x200000), 0x200000); + munmap((void *)((uintptr_t)psxRegs.ptrs.psxM + i * 0x200000), 0x200000); return err; } @@ -228,9 +228,9 @@ void lightrec_free_mmap(void) unsigned int i; munmap(code_buffer, CODE_BUFFER_SIZE); - munmap(psxH, 0x10000); - munmap(psxR, 0x200000); - munmap(psxP, 0x10000); + munmap(psxRegs.ptrs.psxH, 0x10000); + munmap(psxRegs.ptrs.psxR, 0x200000); + munmap(psxRegs.ptrs.psxP, 0x10000); for (i = 0; i < 4; i++) - munmap((void *)((uintptr_t)psxM + i * 0x200000), 0x200000); + munmap((void *)((uintptr_t)psxRegs.ptrs.psxM + i * 0x200000), 0x200000); } diff --git a/libpcsxcore/lightrec/plugin.c b/libpcsxcore/lightrec/plugin.c index 3e112654..bdee4086 100644 --- a/libpcsxcore/lightrec/plugin.c +++ b/libpcsxcore/lightrec/plugin.c @@ -362,9 +362,9 @@ static struct lightrec_mem_map lightrec_map[] = { static void lightrec_enable_ram(struct lightrec_state *state, bool enable) { if (enable) - memcpy(psxM, cache_buf, sizeof(cache_buf)); + memcpy(psxRegs.ptrs.psxM, cache_buf, sizeof(cache_buf)); else - memcpy(cache_buf, psxM, sizeof(cache_buf)); + memcpy(cache_buf, psxRegs.ptrs.psxM, sizeof(cache_buf)); ram_disabled = !enable; } @@ -462,11 +462,11 @@ static const struct lightrec_ops lightrec_ops = { static int lightrec_plugin_init(void) { - lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxM; - lightrec_map[PSX_MAP_BIOS].address = psxR; - lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH; - lightrec_map[PSX_MAP_HW_REGISTERS].address = psxH + 0x1000; - lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP; + lightrec_map[PSX_MAP_KERNEL_USER_RAM].address = psxRegs.ptrs.psxM; + lightrec_map[PSX_MAP_BIOS].address = psxRegs.ptrs.psxR; + lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxRegs.ptrs.psxH; + lightrec_map[PSX_MAP_HW_REGISTERS].address = psxRegs.ptrs.psxH + 0x1000; + lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxRegs.ptrs.psxP; if (!LIGHTREC_CUSTOM_MAP) { #if P_HAVE_MMAP @@ -483,9 +483,9 @@ static int lightrec_plugin_init(void) } if (LIGHTREC_CUSTOM_MAP) { - lightrec_map[PSX_MAP_MIRROR1].address = psxM + 0x200000; - lightrec_map[PSX_MAP_MIRROR2].address = psxM + 0x400000; - lightrec_map[PSX_MAP_MIRROR3].address = psxM + 0x600000; + lightrec_map[PSX_MAP_MIRROR1].address = psxRegs.ptrs.psxM + 0x200000; + lightrec_map[PSX_MAP_MIRROR2].address = psxRegs.ptrs.psxM + 0x400000; + lightrec_map[PSX_MAP_MIRROR3].address = psxRegs.ptrs.psxM + 0x600000; } lightrec_map[PSX_MAP_CODE_BUFFER].address = code_buffer; @@ -507,10 +507,10 @@ static int lightrec_plugin_init(void) &lightrec_ops); // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n", - // (uintptr_t) psxM, - // (uintptr_t) psxP, - // (uintptr_t) psxR, - // (uintptr_t) psxH); + // (uintptr_t) psxRegs.ptrs.psxM, + // (uintptr_t) psxRegs.ptrs.psxP, + // (uintptr_t) psxRegs.ptrs.psxR, + // (uintptr_t) psxRegs.ptrs.psxH); #ifndef _WIN32 signal(SIGPIPE, exit); @@ -587,9 +587,9 @@ static void print_for_big_ass_debugger(void) 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)); + hash_calculate_ram(psxRegs.ptrs.psxM, 0x200000), + hash_calculate_le(psxRegs.ptrs.psxH, 0x400), + hash_calculate_le(psxRegs.ptrs.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)), diff --git a/libpcsxcore/mdec.c b/libpcsxcore/mdec.c index f42e67bf..18b85666 100644 --- a/libpcsxcore/mdec.c +++ b/libpcsxcore/mdec.c @@ -457,7 +457,7 @@ void mdecInit(void) { memset(&mdec, 0, sizeof(mdec)); memset(iq_y, 0, sizeof(iq_y)); memset(iq_uv, 0, sizeof(iq_uv)); - mdec.rl = (u16 *)&psxM[0x100000]; + mdec.rl = (u16 *)&psxRegs.ptrs.psxM[0x100000]; } // command register @@ -705,7 +705,7 @@ void mdec1Interrupt() { } int mdecFreeze(void *f, int Mode) { - u8 *base = (u8 *)psxM; + u8 *base = (u8 *)psxRegs.ptrs.psxM; u32 v; gzfreeze(&mdec.reg0, sizeof(mdec.reg0)); diff --git a/libpcsxcore/misc.c b/libpcsxcore/misc.c index 145b964c..fcac1a8b 100644 --- a/libpcsxcore/misc.c +++ b/libpcsxcore/misc.c @@ -703,7 +703,7 @@ struct misc_save_data { #define EX_SCREENPIC_SIZE (128 * 96 * 3) int SaveState(const char *file) { - struct misc_save_data *misc = (void *)(psxH + 0xf000); + struct misc_save_data *misc = (void *)(psxRegs.ptrs.psxH + 0xf000); struct origin_info oi = { 0, }; GPUFreeze_t *gpufP = NULL; SPUFreezeHdr_t spufH; @@ -757,9 +757,9 @@ int SaveState(const char *file) { if (Config.HLE) psxBiosFreeze(1); - SaveFuncs.write(f, psxM, 0x00200000); - SaveFuncs.write(f, psxR, 0x00080000); - SaveFuncs.write(f, psxH, 0x00010000); + SaveFuncs.write(f, psxRegs.ptrs.psxM, 0x00200000); + SaveFuncs.write(f, psxRegs.ptrs.psxR, 0x00080000); + SaveFuncs.write(f, psxRegs.ptrs.psxH, 0x00010000); // only partial save of psxRegisters to maintain savestate compat SaveFuncs.write(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle)); @@ -797,7 +797,7 @@ cleanup: } int LoadState(const char *file) { - struct misc_save_data *misc = (void *)(psxH + 0xf000); + struct misc_save_data *misc = (void *)(psxRegs.ptrs.psxH + 0xf000); u32 biosBranchCheckOld = psxRegs.biosBranchCheck; void *f; GPUFreeze_t *gpufP = NULL; @@ -841,9 +841,9 @@ int LoadState(const char *file) { // ex-ScreenPic space SaveFuncs.seek(f, EX_SCREENPIC_SIZE, SEEK_CUR); - SaveFuncs.read(f, psxM, 0x00200000); - SaveFuncs.read(f, psxR, 0x00080000); - SaveFuncs.read(f, psxH, 0x00010000); + SaveFuncs.read(f, psxRegs.ptrs.psxM, 0x00200000); + SaveFuncs.read(f, psxRegs.ptrs.psxR, 0x00080000); + SaveFuncs.read(f, psxRegs.ptrs.psxH, 0x00010000); SaveFuncs.read(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle)); psxRegs.gteBusyCycle = psxRegs.cycle; psxRegs.branching = 0; diff --git a/libpcsxcore/new_dynarec/emu_if.c b/libpcsxcore/new_dynarec/emu_if.c index 7880e02a..48027464 100644 --- a/libpcsxcore/new_dynarec/emu_if.c +++ b/libpcsxcore/new_dynarec/emu_if.c @@ -616,7 +616,7 @@ static int ari64_init() #ifdef DRC_DBG memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf)); #endif - psxH_ptr = psxH; + psxH_ptr = psxRegs.ptrs.psxH; zeromem_ptr = zero_mem; scratch_buf_ptr = scratch_buf; // for gte_neon.S diff --git a/libpcsxcore/new_dynarec/linkage_offsets.h b/libpcsxcore/new_dynarec/linkage_offsets.h index 53cef59b..29be3b19 100644 --- a/libpcsxcore/new_dynarec/linkage_offsets.h +++ b/libpcsxcore/new_dynarec/linkage_offsets.h @@ -23,8 +23,9 @@ #define LO_muldivBusyCycle (LO_gteBusyCycle + 4) #define LO_psxRegs_subCycle (LO_muldivBusyCycle + 4) #define LO_psxRegs_biuReg (LO_psxRegs_subCycle + 4*2) -#define LO_stop (LO_psxRegs_biuReg + 4) -#define LO_psxRegs_end (LO_stop + 4*9) +#define LO_stop (LO_psxRegs_biuReg + 4) +#define LO_psxRegs_ptrs (LO_stop + 4*7) +#define LO_psxRegs_end (LO_psxRegs_ptrs + PTRSZ*10) #define LO_rcnts (LO_psxRegs_end) #define LO_rcnts_end (LO_rcnts + 7*4*4) #define LO_inv_code_start (LO_rcnts_end) diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 1111588c..e31d2291 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -2967,7 +2967,7 @@ static void *emit_fastpath_cmp_jump(int i, const struct regstat *i_regs, type=0; } else if(type==MTYPE_1F80) { // scratchpad - if (psxH == (void *)0x1f800000) { + if (psxRegs.ptrs.psxH == (void *)0x1f800000) { host_tempreg_acquire(); emit_xorimm(addr,0x1f800000,HOST_TEMPREG); emit_cmpimm(HOST_TEMPREG,0x1000); @@ -6470,11 +6470,12 @@ void new_dynarec_init(void) #endif arch_init(); new_dynarec_test(); - ram_offset = (uintptr_t)psxM - 0x80000000; + ram_offset = (uintptr_t)psxRegs.ptrs.psxM - 0x80000000; if (ram_offset != 0) SysPrintf("RAM is not directly mapped\n"); SysPrintf("Mapped (RAM/scrp/ROM/LUTs/TC):\n"); - SysPrintf("%p/%p/%p/%p/%p\n", psxM, psxH, psxR, mem_rtab, out); + SysPrintf("%p/%p/%p/%p/%p\n", psxRegs.ptrs.psxM, psxRegs.ptrs.psxH, + psxRegs.ptrs.psxR, mem_rtab, out); } void new_dynarec_cleanup(void) @@ -6513,7 +6514,7 @@ static u_int *get_source_start(u_int addr, u_int *limit) { // used for BIOS calls mostly? *limit = (addr & 0xa0600000) + 0x00200000; - return (u_int *)(psxM + (addr & 0x1fffff)); + return (u_int *)(psxRegs.ptrs.psxM + (addr & 0x1fffff)); } else if ( (0x9fc00000u <= addr && addr < 0x9fc80000u) || @@ -6526,7 +6527,7 @@ static u_int *get_source_start(u_int addr, u_int *limit) // cycle_multiplier_active = 200; *limit = (addr & 0xfff00000) | 0x80000; - return (u_int *)((u_char *)psxR + (addr&0x7ffff)); + return (u_int *)((u_char *)psxRegs.ptrs.psxR + (addr&0x7ffff)); } return NULL; } @@ -6682,7 +6683,7 @@ static noinline void do_vsync(int i) if (!is_ram_addr(addr)) return; - str = (char *)psxM + (addr & 0x1fffff); + str = (char *)psxRegs.ptrs.psxM + (addr & 0x1fffff); if (!str || strncmp(str, "VSync: timeout", 14)) return; // jal clearPad, jal clearRCnt; j return; nop diff --git a/libpcsxcore/new_dynarec/pcsxmem.c b/libpcsxcore/new_dynarec/pcsxmem.c index 98e2c6be..804330b7 100644 --- a/libpcsxcore/new_dynarec/pcsxmem.c +++ b/libpcsxcore/new_dynarec/pcsxmem.c @@ -130,8 +130,8 @@ static void map_rcnt_rcount1(u32 mode) static void map_rcnt_rcount2(u32 mode) { if ((mode & 7) == 1 || (mode & 7) == 7) { // sync mode - map_item(&mem_iortab[IOMEM32(0x1120)], &psxH[0x1000], 0); - map_item(&mem_iortab[IOMEM16(0x1120)], &psxH[0x1000], 0); + map_item(&mem_iortab[IOMEM32(0x1120)], &psxRegs.ptrs.psxH[0x1000], 0); + map_item(&mem_iortab[IOMEM16(0x1120)], &psxRegs.ptrs.psxH[0x1000], 0); } else if (mode & 0x200) { // clk/8 map_item(&mem_iortab[IOMEM32(0x1120)], rcnt2_read_count_m1, 1); @@ -214,9 +214,10 @@ void new_dyna_pcsx_mem_isolate(int enable) } else { 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); + void *ram = psxRegs.ptrs.psxM; + map_l1_mem(mem_writetab, i, 0x80000000, 0x200000, ram); + map_l1_mem(mem_writetab, i, 0x00000000, 0x200000, ram); + map_l1_mem(mem_writetab, i, 0xa0000000, 0x200000, ram); } } } @@ -308,25 +309,26 @@ void new_dyna_pcsx_mem_init(void) map_item(&mem_writetab[i], mem_unmwtab, 1); } - // RAM and it's mirrors + // RAM and its 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); + void *ram = psxRegs.ptrs.psxM; + map_l1_mem(mem_readtab, i, 0x80000000, 0x200000, ram); + map_l1_mem(mem_readtab, i, 0x00000000, 0x200000, ram); + map_l1_mem(mem_readtab, i, 0xa0000000, 0x200000, ram); } new_dyna_pcsx_mem_isolate(0); - // BIOS and it's mirrors + // BIOS and its 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); + map_l1_mem(mem_readtab, i, 0x1fc00000, 0x80000, psxRegs.ptrs.psxR); + map_l1_mem(mem_readtab, i, 0xbfc00000, 0x80000, psxRegs.ptrs.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); + map_l1_mem(mem_readtab, 0, 0x1f800000, 0x1000, psxRegs.ptrs.psxH); + map_l1_mem(mem_readtab, 0, 0x9f800000, 0x1000, psxRegs.ptrs.psxH); + map_l1_mem(mem_writetab, 0, 0x1f800000, 0x1000, psxRegs.ptrs.psxH); + map_l1_mem(mem_writetab, 0, 0x9f800000, 0x1000, psxRegs.ptrs.psxH); // I/O map_item(&mem_readtab[0x1f801000u >> 12], mem_iortab, 1); @@ -343,16 +345,16 @@ void new_dyna_pcsx_mem_init(void) // 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); + map_item(&mem_iortab[i], &psxRegs.ptrs.psxH[0x1000], 0); + map_item(&mem_iowtab[i], &psxRegs.ptrs.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); + map_item(&mem_iortab[i], &psxRegs.ptrs.psxH[0x1000], 0); + map_item(&mem_iowtab[i], &psxRegs.ptrs.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[i], &psxRegs.ptrs.psxH[0x1000], 0); + map_item(&mem_iowtab[i], &psxRegs.ptrs.psxH[0x1000], 0); } map_item(&mem_iortab[IOMEM32(0x1040)], io_read_sio32, 1); diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index accecb85..500cc27c 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -332,25 +332,25 @@ static int card_io_delay; static u8 loadRam8(u32 addr) { assert(!(addr & 0x5f800000)); - return psxM[addr & 0x1fffff]; + return psxRegs.ptrs.psxM[addr & 0x1fffff]; } static u32 loadRam32(u32 addr) { assert(!(addr & 0x5f800000)); - return SWAP32(*((u32 *)psxM + ((addr & 0x1fffff) >> 2))); + return SWAP32(*((u32 *)psxRegs.ptrs.psxM + ((addr & 0x1fffff) >> 2))); } static void *castRam8ptr(u32 addr) { assert(!(addr & 0x5f800000)); - return psxM + (addr & 0x1fffff); + return psxRegs.ptrs.psxM + (addr & 0x1fffff); } static void *castRam32ptr(u32 addr) { assert(!(addr & 0x5f800003)); - return psxM + (addr & 0x1ffffc); + return psxRegs.ptrs.psxM + (addr & 0x1ffffc); } static void *loadRam8ptr(u32 addr) @@ -366,13 +366,13 @@ static void *loadRam32ptr(u32 addr) static void storeRam8(u32 addr, u8 d) { assert(!(addr & 0x5f800000)); - *((u8 *)psxM + (addr & 0x1fffff)) = d; + *((u8 *)psxRegs.ptrs.psxM + (addr & 0x1fffff)) = d; } static void storeRam32(u32 addr, u32 d) { assert(!(addr & 0x5f800000)); - *((u32 *)psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d); + *((u32 *)psxRegs.ptrs.psxM + ((addr & 0x1fffff) >> 2)) = SWAP32(d); } static void mips_return(u32 val) @@ -514,7 +514,7 @@ static int card_buf_io(int is_write, int port, void *buf, u32 size) SaveMcd(Config.Mcd2, Mcd2Data, offset, size); } else { - size_t ram_offset = (s8 *)buf - psxM; + size_t ram_offset = (u8 *)buf - psxRegs.ptrs.psxM; memcpy(buf, mcdptr + offset, size); if (ram_offset < 0x200000) psxCpu->Clear(ram_offset, (size + 3) / 4); @@ -1902,7 +1902,7 @@ static void psxBios_SysDeqIntRP_(u32 priority, u32 chain_rm_eptr); static void psxBios_EnqueueCdIntr_(void) { - u32 *ram32 = (u32 *)psxM; + u32 *ram32 = (u32 *)psxRegs.ptrs.psxM; // traps should already be installed by write_chain() ram32[0x91d0/4] = 0; @@ -2056,7 +2056,7 @@ static void psxBios_GetSystemInfo() { // b4 SysPrintf("psxBios_%s %x\n", biosA0n[0xb4], a0); switch (a0) { case 0: - case 1: ret = SWAP32(((u32 *)psxR)[0x100/4 + a0]); break; + case 1: ret = SWAP32(((u32 *)psxRegs.ptrs.psxR)[0x100/4 + a0]); break; case 2: ret = 0xbfc0012c; break; case 5: ret = loadRam32(0x60) << 10; break; } @@ -2403,7 +2403,7 @@ void psxBios_ChangeTh() { // 10 } void psxBios_InitPAD() { // 0x12 - u32 i, *ram32 = (u32 *)psxM; + u32 i, *ram32 = (u32 *)psxRegs.ptrs.psxM; PSXBIOS_LOG("psxBios_%s %x %x %x %x\n", biosB0n[0x12], a0, a1, a2, a3); // printf("%s", "PS-X Control PAD Driver Ver 3.0"); @@ -2948,8 +2948,8 @@ void psxBios_delete() { // 45 } void psxBios_InitCARD() { // 4a - u8 *ram8 = (u8 *)psxM; - u32 *ram32 = (u32 *)psxM; + u8 *ram8 = (u8 *)psxRegs.ptrs.psxM; + u32 *ram32 = (u32 *)psxRegs.ptrs.psxM; PSXBIOS_LOG("psxBios_%s: %x\n", biosB0n[0x4a], a0); write_chain(ram32 + A_PADCRD_CHN_E/4, 0, 0x49bc, 0x4a4c); //card_error = 0; @@ -3406,12 +3406,12 @@ void (**biosB0)() = biosC0 + 128; static void setup_mips_code() { u32 *ptr; - ptr = (u32 *)&psxM[A_SYSCALL]; + ptr = (u32 *)&psxRegs.ptrs.psxM[A_SYSCALL]; ptr[0x00/4] = SWAPu32(0x0000000c); // syscall 0 ptr[0x04/4] = SWAPu32(0x03e00008); // jr $ra ptr[0x08/4] = SWAPu32(0x00000000); // nop - ptr = (u32 *)&psxM[A_EXCEPTION]; + ptr = (u32 *)&psxRegs.ptrs.psxM[A_EXCEPTION]; memset(ptr, 0, 0xc0); // nops (to be patched by games sometimes) ptr[0x10/4] = SWAPu32(0x8c1a0108); // lw $k0, (0x108) // PCB ptr[0x14/4] = SWAPu32(0x00000000); // nop @@ -3475,7 +3475,7 @@ static void write_chain(u32 *d, u32 next, u32 handler1, u32 handler2) static void setup_tt(u32 tcb_cnt, u32 evcb_cnt, u32 stack) { - u32 *ram32 = (u32 *)psxM; + u32 *ram32 = (u32 *)psxRegs.ptrs.psxM; u32 s_excb = 0x20, s_evcb, s_pcb = 4, s_tcb; u32 p_excb, p_evcb, p_pcb, p_tcb; u32 i; @@ -3572,7 +3572,7 @@ static void spu_clear_mem(u32 addr, u32 size) void psxBiosSetupBootState(void) { boolean hle = Config.HLE; - u32 *hw = (u32 *)psxH; + u32 *hw = (u32 *)psxRegs.ptrs.psxH; int i; // see also SetBootRegs() @@ -3656,7 +3656,7 @@ void psxBiosInit() { psxRegs.biosBranchCheck = ~0; - memset(psxM, 0, 0x10000); + memset(psxRegs.ptrs.psxM, 0, 0x10000); for(i = 0; i < 256; i++) { biosA0[i] = NULL; biosB0[i] = NULL; @@ -3670,11 +3670,11 @@ void psxBiosInit() { if (!Config.HLE) { char verstr[0x24+1]; - rom32 = (u32 *)psxR; - memcpy(verstr, psxR + 0x12c, 0x24); + rom32 = (u32 *)psxRegs.ptrs.psxR; + memcpy(verstr, psxRegs.ptrs.psxR + 0x12c, 0x24); verstr[0x24] = 0; SysPrintf("BIOS: %08x, '%s', '%c'\n", SWAP32(rom32[0x100/4]), - verstr, psxR[0x7ff52]); + verstr, psxRegs.ptrs.psxR[0x7ff52]); return; } @@ -3999,10 +3999,10 @@ void psxBiosInit() { // somewhat pretend to be a SCPH1001 BIOS // some games look for these and take an exception if they're missing - rom32 = (u32 *)psxR; + rom32 = (u32 *)psxRegs.ptrs.psxR; rom32[0x100/4] = SWAP32(0x19951204); rom32[0x104/4] = SWAP32(3); - romc = (char *)psxR; + romc = (char *)psxRegs.ptrs.psxR; strcpy(romc + 0x108, "PCSX authors"); strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A"); @@ -4010,9 +4010,9 @@ void psxBiosInit() { // fonts len = 0x80000 - 0x66000; - uncompress((Bytef *)(psxR + 0x66000), &len, font_8140, sizeof(font_8140)); + uncompress((Bytef *)(romc + 0x66000), &len, font_8140, sizeof(font_8140)); len = 0x80000 - 0x69d68; - uncompress((Bytef *)(psxR + 0x69d68), &len, font_889f, sizeof(font_889f)); + uncompress((Bytef *)(romc + 0x69d68), &len, font_889f, sizeof(font_889f)); // trap attempts to call bios directly rom32[0x00000/4] = HLEOP(hleop_dummy); @@ -4028,7 +4028,7 @@ void psxBiosInit() { Crash Team Racing will softlock after the Sony logo. */ - ram32 = (u32 *)psxM; + ram32 = (u32 *)psxRegs.ptrs.psxM; ram32[0x0000/4] = SWAPu32(0x00000003); // lui $k0, 0 (overwritten by 3) ram32[0x0004/4] = SWAPu32(0x275a0000 + A_EXCEPTION); // addiu $k0, $k0, 0xc80 ram32[0x0008/4] = SWAPu32(0x03400008); // jr $k0 @@ -4069,12 +4069,12 @@ void psxBiosInit() { // (or rather the funcs listed there) // also trap the destination as some "Cheats Edition" thing overrides the // dispatcher with a wrapper and then jumps to the table entries directly - ptr = (u32 *)&psxM[A_A0_TABLE]; + ptr = (u32 *)&psxRegs.ptrs.psxM[A_A0_TABLE]; for (i = 0; i < 256; i++) { ptr[i] = SWAP32(A_A0_TRAPS + i*4); ram32[A_A0_TRAPS/4 + i] = HLEOP(hleop_a0t); } - ptr = (u32 *)&psxM[A_B0_TABLE]; + ptr = (u32 *)&psxRegs.ptrs.psxM[A_B0_TABLE]; for (i = 0; i < 256; i++) { ptr[i] = SWAP32(A_B0_TRAPS + i*4); ram32[A_B0_TRAPS/4 + i] = HLEOP(hleop_b0t); @@ -4095,7 +4095,7 @@ void psxBiosInit() { ram32[0x4c64/4] = SWAP32(0x03e00008); // jr $ra ram32[0x4c68/4] = SWAP32(0xac000000 + A_PAD_IRQR_ENA); // sw $0, ... - ptr = (u32 *)&psxM[A_C0_TABLE]; + ptr = (u32 *)&psxRegs.ptrs.psxM[A_C0_TABLE]; for (i = 0; i < 256/2; i++) { ptr[i] = SWAP32(A_C0_TRAPS + i*4); ram32[A_C0_TRAPS/4 + i] = HLEOP(hleop_c0t); @@ -4574,7 +4574,7 @@ void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state) u32 start = t_addr & 0x1ffffc; u32 end = (start + t_size) & 0x1ffffc; u32 buf[sizeof(pattern) / sizeof(u32)]; - const u32 *r32 = (u32 *)(psxM + start); + const u32 *r32 = (u32 *)(psxRegs.ptrs.psxM + start); u32 i, j; if (end <= start) @@ -4625,8 +4625,8 @@ void psxBiosCheckBranch(void) } #define bfreeze(ptr, size) { \ - if (Mode == 1) memcpy(&psxR[base], ptr, size); \ - if (Mode == 0) memcpy(ptr, &psxR[base], size); \ + if (Mode == 1) memcpy(&psxRegs.ptrs.psxR[base], ptr, size); \ + if (Mode == 0) memcpy(ptr, &psxRegs.ptrs.psxR[base], size); \ base += size; \ } diff --git a/libpcsxcore/psxdma.c b/libpcsxcore/psxdma.c index 6dc5d63b..6904c432 100644 --- a/libpcsxcore/psxdma.c +++ b/libpcsxcore/psxdma.c @@ -200,7 +200,7 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU do_walking = Config.hacks.gpu_slow_list_walking; madr_next_p = do_walking ? &madr_next : NULL; - cycles_sum = GPU_dmaChain((u32 *)psxM, madr & 0x1fffff, + cycles_sum = GPU_dmaChain((u32 *)psxRegs.ptrs.psxM, madr & 0x1fffff, madr_next_p, &cycles_last_cmd); HW_DMA2_MADR = SWAPu32(madr_next); @@ -234,8 +234,8 @@ void gpuInterrupt() { do { cycles_sum += cycles_last_cmd; - cycles_sum += GPU_dmaChain((u32 *)psxM, madr_next & 0x1fffff, - &madr_next, &cycles_last_cmd); + cycles_sum += GPU_dmaChain((u32 *)psxRegs.ptrs.psxM, + madr_next & 0x1fffff, &madr_next, &cycles_last_cmd); } while (cycles_sum <= 0 && !(madr_next & 0x800000)); HW_DMA2_MADR = SWAPu32(madr_next); @@ -275,7 +275,7 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr) { // already 32-bit size words = bcr; - while (bcr-- && mem > (u32 *)psxM) { + while (bcr-- && mem > (u32 *)psxRegs.ptrs.psxM) { *mem-- = SWAP32((madr - 4) & 0xffffff); madr -= 4; } diff --git a/libpcsxcore/psxdma.h b/libpcsxcore/psxdma.h index ce10d9d3..88bb10f5 100644 --- a/libpcsxcore/psxdma.h +++ b/libpcsxcore/psxdma.h @@ -45,7 +45,7 @@ static inline void *getDmaRam(u32 madr, u32 *max_words) if (!(madr & 0x800000)) { madr &= 0x1ffffc; *max_words = (0x200000 - madr) / 4; - return psxM + madr; + return psxRegs.ptrs.psxM + madr; } return INVALID_PTR; } diff --git a/libpcsxcore/psxhw.c b/libpcsxcore/psxhw.c index 1afa9c61..69d3d037 100644 --- a/libpcsxcore/psxhw.c +++ b/libpcsxcore/psxhw.c @@ -29,7 +29,7 @@ #include "../include/compiler_features.h" void psxHwReset() { - memset(psxH, 0, 0x10000); + memset(psxRegs.ptrs.psxH, 0, 0x10000); mdecInit(); // initialize mdec decoder cdrReset(); @@ -438,6 +438,11 @@ void psxHwWrite32(u32 add, u32 value) { case 0x1124: psxRcntWmode(2, value); return; case 0x1128: psxRcntWtarget(2, value & 0xffff); return; + case 0x1060: + if ((value >> 9) != 5) + log_unhandled("unhandled RAM_SIZE %08x @%08x\n", value, psxRegs.pc); + break; + case 0x1044: case 0x1048: case 0x104c: diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 68d79321..ad69c5f0 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -36,11 +36,6 @@ #define DO_EXCEPTION_RESERVEDI #define HANDLE_LOAD_DELAY -#ifdef __i386__ -#define INT_ATTR __attribute__((regparm(2))) -#else -#define INT_ATTR -#endif #ifndef INVALID_PTR #define INVALID_PTR NULL #endif @@ -174,17 +169,17 @@ static int execBreakCheck(psxRegisters *regs, u32 pc) // get an opcode without triggering exceptions or affecting cache u32 intFakeFetch(u32 pc) { - u32 *code = (u32 *)psxm(pc & ~0x3, 0); - if (unlikely(code == INVALID_PTR)) + const u32 *code; + if (!psxm_lut((u8 **)&code, &psxRegs, pc & ~0x3, 0, psxRegs.ptrs.memRLUT)) return 0; // nop return SWAP32(*code); } -static u32 INT_ATTR fetchNoCache(psxRegisters *regs, u8 **memRLUT, u32 pc) +static u32 INT_ATTR fetchNoCache(psxRegisters *regs, const uintptr_t *memRLUT, u32 pc) { - u32 *code = (u32 *)psxm_lut(pc & ~0x3, 0, memRLUT); - if (unlikely(code == INVALID_PTR)) { + const u32 *code; + if (!psxm_lut((u8 **)&code, regs, pc & ~0x3, 0, memRLUT)) { SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra); intException(regs, pc, R3000E_IBE << 2); return 0; // execute as nop @@ -201,7 +196,7 @@ static struct cache_entry { u32 data[4]; } ICache[256]; -static u32 INT_ATTR fetchICache(psxRegisters *regs, u8 **memRLUT, u32 pc) +static u32 INT_ATTR fetchICache(psxRegisters *regs, const uintptr_t *memRLUT, u32 pc) { // cached? if (pc < 0xa0000000) @@ -211,8 +206,8 @@ static u32 INT_ATTR fetchICache(psxRegisters *regs, u8 **memRLUT, u32 pc) if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag) { - const u32 *code = (u32 *)psxm_lut(pc & ~0xf, 0, memRLUT); - if (unlikely(code == INVALID_PTR)) { + const u32 *code; + if (!psxm_lut((u8 **)&code, regs, pc & ~0x0f, 0, memRLUT)) { SysPrintf("game crash @%08x, ra=%08x\n", pc, regs->GPR.n.ra); intException(regs, pc, R3000E_IBE << 2); return 0; // execute as nop @@ -234,8 +229,6 @@ static u32 INT_ATTR fetchICache(psxRegisters *regs, u8 **memRLUT, u32 pc) return fetchNoCache(regs, memRLUT, pc); } -static u32 (INT_ATTR *fetch)(psxRegisters *regs_, u8 **memRLUT, u32 pc) = fetchNoCache; - // Make the timing events trigger faster as we are currently assuming everything // takes one cycle, which is not the case on real hardware. // FIXME: count cache misses, memory latencies, stalls to get rid of this @@ -390,7 +383,8 @@ static void psxDoDelayBranch(psxRegisters *regs, u32 tar1, u32 code1) { * has no normal delay slot, instruction at tar1 was fetched instead) */ for (lim = 0; lim < 8; lim++) { - regs->code = code = fetch(regs, psxMemRLUT, tar1); + code = regs->ptrs.intFetch(regs, regs->ptrs.memRLUT, tar1); + regs->code = code; addCycle(regs); if (likely(!isBranch(code))) { dloadStep(regs); @@ -416,7 +410,7 @@ static void doBranch(psxRegisters *regs, u32 tar, enum R3000Abdt taken) { // fetch the delay slot pc = regs->pc; regs->pc = pc + 4; - regs->code = code = fetch(regs, psxMemRLUT, pc); + regs->code = code = regs->ptrs.intFetch(regs, regs->ptrs.memRLUT, pc); addCycle(regs); @@ -664,15 +658,17 @@ OP(psxSYSCALL) { intExceptionInsn(regs_, R3000E_Syscall << 2); } -static inline void execI_(u8 **memRLUT, psxRegisters *regs_); +static inline void execI_( + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc), + const uintptr_t *memRLUT, psxRegisters *regs); -static inline void psxTestSWInts(psxRegisters *regs_, int step) { - if ((regs_->CP0.n.Cause & regs_->CP0.n.SR & 0x0300) && - (regs_->CP0.n.SR & 0x1)) { +static inline void psxTestSWInts(psxRegisters *regs, int step) { + if ((regs->CP0.n.Cause & regs->CP0.n.SR & 0x0300) && + (regs->CP0.n.SR & 0x1)) { if (step) - execI_(psxMemRLUT, regs_); - regs_->CP0.n.Cause &= ~0x7c; - intException(regs_, regs_->pc, regs_->CP0.n.Cause); + execI_(regs->ptrs.intFetch, regs->ptrs.memRLUT, regs); + regs->CP0.n.Cause &= ~0x7c; + intException(regs, regs->pc, regs->CP0.n.Cause); } } @@ -801,17 +797,17 @@ static inline int checkST(psxRegisters *regs, u32 addr, u32 m) { #define _oB_ (regs_->GPR.r[_Rs_] + _Imm_) -OP(psxLB) { doLoad(regs_, _Rt_, (s8)psxMemRead8(_oB_)); } -OP(psxLBU) { doLoad(regs_, _Rt_, psxMemRead8(_oB_)); } -OP(psxLH) { doLoad(regs_, _Rt_, (s16)psxMemRead16(_oB_ & ~1)); } -OP(psxLHU) { doLoad(regs_, _Rt_, psxMemRead16(_oB_ & ~1)); } -OP(psxLW) { doLoad(regs_, _Rt_, psxMemRead32(_oB_ & ~3)); } +OP(psxLB) { doLoad(regs_, _Rt_, (s8)psxMemRead8(regs_, _oB_)); } +OP(psxLBU) { doLoad(regs_, _Rt_, psxMemRead8(regs_, _oB_)); } +OP(psxLH) { doLoad(regs_, _Rt_, (s16)psxMemRead16(regs_, _oB_ & ~1)); } +OP(psxLHU) { doLoad(regs_, _Rt_, psxMemRead16(regs_, _oB_ & ~1)); } +OP(psxLW) { doLoad(regs_, _Rt_, psxMemRead32(regs_, _oB_ & ~3)); } -OP(psxLBe) { if (checkLD(regs_, _oB_, 0)) doLoad(regs_, _Rt_, (s8)psxMemRead8(_oB_)); } -OP(psxLBUe) { if (checkLD(regs_, _oB_, 0)) doLoad(regs_, _Rt_, psxMemRead8(_oB_)); } -OP(psxLHe) { if (checkLD(regs_, _oB_, 1)) doLoad(regs_, _Rt_, (s16)psxMemRead16(_oB_)); } -OP(psxLHUe) { if (checkLD(regs_, _oB_, 1)) doLoad(regs_, _Rt_, psxMemRead16(_oB_)); } -OP(psxLWe) { if (checkLD(regs_, _oB_, 3)) doLoad(regs_, _Rt_, psxMemRead32(_oB_)); } +OP(psxLBe) { if (checkLD(regs_, _oB_, 0)) doLoad(regs_, _Rt_, (s8)psxMemRead8(regs_, _oB_)); } +OP(psxLBUe) { if (checkLD(regs_, _oB_, 0)) doLoad(regs_, _Rt_, psxMemRead8(regs_, _oB_)); } +OP(psxLHe) { if (checkLD(regs_, _oB_, 1)) doLoad(regs_, _Rt_, (s16)psxMemRead16(regs_, _oB_)); } +OP(psxLHUe) { if (checkLD(regs_, _oB_, 1)) doLoad(regs_, _Rt_, psxMemRead16(regs_, _oB_)); } +OP(psxLWe) { if (checkLD(regs_, _oB_, 3)) doLoad(regs_, _Rt_, psxMemRead32(regs_, _oB_)); } static void doLWL(psxRegisters *regs, u32 rt, u32 addr) { static const u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 }; @@ -825,7 +821,7 @@ static void doLWL(psxRegisters *regs, u32 rt, u32 addr) { if (regs->dloadReg[sel] == rt) oldval = regs->dloadVal[sel]; #endif - mem = psxMemRead32(addr & ~3); + mem = psxMemRead32(regs, addr & ~3); val = (oldval & LWL_MASK[shift]) | (mem << LWL_SHIFT[shift]); doLoad(regs, rt, val); @@ -851,7 +847,7 @@ static void doLWR(psxRegisters *regs, u32 rt, u32 addr) { if (regs->dloadReg[sel] == rt) oldval = regs->dloadVal[sel]; #endif - mem = psxMemRead32(addr & ~3); + mem = psxMemRead32(regs, addr & ~3); val = (oldval & LWR_MASK[shift]) | (mem >> LWR_SHIFT[shift]); doLoad(regs, rt, val); @@ -871,23 +867,23 @@ OP(psxLWR) { doLWR(regs_, _Rt_, _oB_); } OP(psxLWLe) { if (checkLD(regs_, _oB_ & ~3, 0)) doLWL(regs_, _Rt_, _oB_); } OP(psxLWRe) { if (checkLD(regs_, _oB_ , 0)) doLWR(regs_, _Rt_, _oB_); } -OP(psxSB) { psxMemWrite8 (_oB_, _rRt_); } -OP(psxSH) { psxMemWrite16(_oB_, _rRt_); } -OP(psxSW) { psxMemWrite32(_oB_, _rRt_); } +OP(psxSB) { psxMemWrite8 (regs_, _oB_, _rRt_); } +OP(psxSH) { psxMemWrite16(regs_, _oB_, _rRt_); } +OP(psxSW) { psxMemWrite32(regs_, _oB_, _rRt_); } -OP(psxSBe) { if (checkST(regs_, _oB_, 0)) psxMemWrite8 (_oB_, _rRt_); } -OP(psxSHe) { if (checkST(regs_, _oB_, 1)) psxMemWrite16(_oB_, _rRt_); } -OP(psxSWe) { if (checkST(regs_, _oB_, 3)) psxMemWrite32(_oB_, _rRt_); } +OP(psxSBe) { if (checkST(regs_, _oB_, 0)) psxMemWrite8 (regs_, _oB_, _rRt_); } +OP(psxSHe) { if (checkST(regs_, _oB_, 1)) psxMemWrite16(regs_, _oB_, _rRt_); } +OP(psxSWe) { if (checkST(regs_, _oB_, 3)) psxMemWrite32(regs_, _oB_, _rRt_); } static void doSWL(psxRegisters *regs, u32 rt, u32 addr) { u32 val = regs->GPR.r[rt]; switch (addr & 3) { - case 0: psxMemWrite8( addr , val >> 24); break; - case 1: psxMemWrite16(addr & ~3, val >> 16); break; + case 0: psxMemWrite8( regs, addr , val >> 24); break; + case 1: psxMemWrite16(regs, addr & ~3, val >> 16); break; case 2: // revisit: should be a single 24bit write - psxMemWrite16(addr & ~3, (val >> 8) & 0xffff); - psxMemWrite8( addr , val >> 24); break; - case 3: psxMemWrite32(addr & ~3, val); break; + psxMemWrite16(regs, addr & ~3, (val >> 8) & 0xffff); + psxMemWrite8( regs, addr , val >> 24); break; + case 3: psxMemWrite32(regs, addr & ~3, val); break; } /* Mem = 1234. Reg = abcd @@ -902,12 +898,12 @@ static void doSWL(psxRegisters *regs, u32 rt, u32 addr) { static void doSWR(psxRegisters *regs, u32 rt, u32 addr) { u32 val = regs->GPR.r[rt]; switch (addr & 3) { - case 0: psxMemWrite32(addr , val); break; + case 0: psxMemWrite32(regs, addr , val); break; case 1: // revisit: should be a single 24bit write - psxMemWrite8 (addr , val & 0xff); - psxMemWrite16(addr + 1, (val >> 8) & 0xffff); break; - case 2: psxMemWrite16(addr , val & 0xffff); break; - case 3: psxMemWrite8 (addr , val & 0xff); break; + psxMemWrite8 (regs, addr , val & 0xff); + psxMemWrite16(regs, addr + 1, (val >> 8) & 0xffff); break; + case 2: psxMemWrite16(regs, addr , val & 0xffff); break; + case 3: psxMemWrite8 (regs, addr , val & 0xff); break; } /* @@ -1053,7 +1049,7 @@ OP(psxCOP2_stall) { } OP(gteLWC2) { - MTC2(®s_->CP2, psxMemRead32(_oB_), _Rt_); + MTC2(®s_->CP2, psxMemRead32(regs_, _oB_), _Rt_); } OP(gteLWC2_stall) { @@ -1064,11 +1060,11 @@ OP(gteLWC2_stall) { OP(gteLWC2e_stall) { gteCheckStall(0); if (checkLD(regs_, _oB_, 3)) - MTC2(®s_->CP2, psxMemRead32(_oB_), _Rt_); + MTC2(®s_->CP2, psxMemRead32(regs_, _oB_), _Rt_); } OP(gteSWC2) { - psxMemWrite32(_oB_, MFC2(®s_->CP2, _Rt_)); + psxMemWrite32(regs_, _oB_, MFC2(®s_->CP2, _Rt_)); } OP(gteSWC2_stall) { @@ -1179,7 +1175,10 @@ static void intReset() { psxRegs.subCycle = 0; } -static inline void execI_(u8 **memRLUT, psxRegisters *regs) { +static inline void execI_( + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc), + const uintptr_t *memRLUT, psxRegisters *regs) +{ u32 pc = regs->pc; addCycle(regs); @@ -1190,7 +1189,10 @@ static inline void execI_(u8 **memRLUT, psxRegisters *regs) { psxBSC[regs->code >> 26](regs, regs->code); } -static inline void execIbp(u8 **memRLUT, psxRegisters *regs) { +static inline void execIbp( + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc), + const uintptr_t *memRLUT, psxRegisters *regs) +{ u32 pc = regs->pc; addCycle(regs); @@ -1205,33 +1207,41 @@ static inline void execIbp(u8 **memRLUT, psxRegisters *regs) { } static void intExecute(psxRegisters *regs) { - u8 **memRLUT = psxMemRLUT; + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc) = + regs->ptrs.intFetch; + const uintptr_t *memRLUT = regs->ptrs.memRLUT; while (!regs->stop) - execI_(memRLUT, regs); + execI_(fetch, memRLUT, regs); } static void intExecuteBp(psxRegisters *regs) { - u8 **memRLUT = psxMemRLUT; + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc) = + regs->ptrs.intFetch; + const uintptr_t *memRLUT = regs->ptrs.memRLUT; while (!regs->stop) - execIbp(memRLUT, regs); + execIbp(fetch, memRLUT, regs); } static void intExecuteBlock(psxRegisters *regs, enum blockExecCaller caller) { - u8 **memRLUT = psxMemRLUT; + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc) = + regs->ptrs.intFetch; + const uintptr_t *memRLUT = regs->ptrs.memRLUT; regs->branchSeen = 0; while (!regs->branchSeen) - execI_(memRLUT, regs); + execI_(fetch, memRLUT, regs); } static void intExecuteBlockBp(psxRegisters *regs, enum blockExecCaller caller) { - u8 **memRLUT = psxMemRLUT; + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc) = + regs->ptrs.intFetch; + const uintptr_t *memRLUT = regs->ptrs.memRLUT; regs->branchSeen = 0; while (!regs->branchSeen) - execIbp(memRLUT, regs); + execIbp(fetch, memRLUT, regs); } static void intClear(u32 Addr, u32 Size) { @@ -1248,7 +1258,7 @@ static void intNotify(enum R3000Anote note, void *data) { setupCop(psxRegs.CP0.n.SR); // fallthrough case R3000ACPU_NOTIFY_CACHE_ISOLATED: // Armored Core? - if (fetch == fetchICache) + if (psxRegs.ptrs.intFetch == fetchICache) memset(&ICache, 0xff, sizeof(ICache)); break; case R3000ACPU_NOTIFY_CACHE_UNISOLATED: @@ -1347,11 +1357,11 @@ void intApplyConfig() { // the dynarec may occasionally call the interpreter, in such a case the // cache won't work (cache only works right if all fetches go through it) if (!Config.icache_emulation || psxCpu != &psxInt) { - fetch = fetchNoCache; + psxRegs.ptrs.intFetch = fetchNoCache; memset(&ICache, 0xff, sizeof(ICache)); } else - fetch = fetchICache; + psxRegs.ptrs.intFetch = fetchICache; cycle_mult = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT ? Config.cycle_multiplier_override : Config.cycle_multiplier; @@ -1365,8 +1375,12 @@ static void intShutdown() { // single step (may do several ops in case of a branch or load delay) // called by asm/dynarec void execI(psxRegisters *regs) { + u32 (INT_ATTR *fetch)(struct psxRegisters *r, const uintptr_t *luts, u32 pc) = + regs->ptrs.intFetch; + const uintptr_t *memRLUT = regs->ptrs.memRLUT; + do { - execIbp(psxMemRLUT, regs); + execIbp(fetch, memRLUT, regs); } while (regs->dloadReg[0] || regs->dloadReg[1]); } diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 9b783cb3..76e555e4 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -24,6 +24,7 @@ // TODO: Implement caches & cycle penalty. #include +#include #include "psxmem.h" #include "psxmem_map.h" #include "r3000a.h" @@ -33,6 +34,7 @@ #include "lightrec/mem.h" #include "memmap.h" +#include "compiler_features.h" #ifdef USE_LIBRETRO_VFS #include @@ -130,14 +132,6 @@ void psxUnmap(void *ptr, size_t size, enum psxMapTag tag) psxUnmapHook(ptr, size, tag); } -s8 *psxM = NULL; // Kernel & User Memory (2 Meg) -s8 *psxP = NULL; // Parallel Port (64K) -s8 *psxR = NULL; // BIOS ROM (512K) -s8 *psxH = NULL; // Scratch Pad (1K) & Hardware Registers (8K) - -u8 **psxMemWLUT = NULL; -u8 **psxMemRLUT = NULL; - /* Playstation Memory Map (from Playstation doc by Joshua Walker) 0x0000_0000-0x0000_ffff Kernel (64K) 0x0001_0000-0x001f_ffff User Memory (1.9 Meg) @@ -159,44 +153,86 @@ u8 **psxMemRLUT = NULL; static int psxMemInitMap(void) { - psxM = psxMap(0x80000000, 0x00210000, 1, MAP_TAG_RAM); - if (psxM == MAP_FAILED) - psxM = psxMap(0x77000000, 0x00210000, 0, MAP_TAG_RAM); - if (psxM == MAP_FAILED) { + u8 *ptr; + + ptr = psxMap(0x80000000, 0x00210000, 1, MAP_TAG_RAM); + if (ptr == MAP_FAILED) + ptr = psxMap(0x77000000, 0x00210000, 0, MAP_TAG_RAM); + if (ptr == MAP_FAILED) { SysMessage("mapping main RAM failed"); - psxM = NULL; return -1; } - psxP = &psxM[0x200000]; + psxRegs.ptrs.psxM = ptr; + psxRegs.ptrs.psxP = ptr + 0x200000; - psxH = psxMap(0x1f800000, 0x10000, 0, MAP_TAG_OTHER); - if (psxH == MAP_FAILED) { + ptr = psxMap(0x1f800000, 0x10000, 0, MAP_TAG_OTHER); + if (ptr == MAP_FAILED) { SysMessage("Error allocating psxH"); - psxH = NULL; return -1; } + psxRegs.ptrs.psxH = ptr; - psxR = psxMap(0x1fc00000, 0x80000, 0, MAP_TAG_OTHER); - if (psxR == MAP_FAILED) { + ptr = psxMap(0x1fc00000, 0x80000, 0, MAP_TAG_OTHER); + if (ptr == MAP_FAILED) { SysMessage("Error allocating psxR"); - psxR = NULL; return -1; } + psxRegs.ptrs.psxR = ptr; return 0; } static void psxMemFreeMap(void) { - if (psxM) psxUnmap(psxM, 0x00210000, MAP_TAG_RAM); - if (psxH) psxUnmap(psxH, 0x10000, MAP_TAG_OTHER); - if (psxR) psxUnmap(psxR, 0x80000, MAP_TAG_OTHER); - psxM = psxH = psxR = NULL; - psxP = NULL; + if (psxRegs.ptrs.psxM) psxUnmap(psxRegs.ptrs.psxM, 0x00210000, MAP_TAG_RAM); + if (psxRegs.ptrs.psxH) psxUnmap(psxRegs.ptrs.psxH, 0x10000, MAP_TAG_OTHER); + if (psxRegs.ptrs.psxR) psxUnmap(psxRegs.ptrs.psxR, 0x80000, MAP_TAG_OTHER); + psxRegs.ptrs.psxM = psxRegs.ptrs.psxH = psxRegs.ptrs.psxR = NULL; + psxRegs.ptrs.psxP = NULL; +} + +static void lutMap(uintptr_t *lut, u8 *mem, u32 size, u32 start, u32 end) +{ + u32 i; + assert((size & ((1u << PSXM_SHIFT) - 1)) == 0); + assert((start & ((1u << PSXM_SHIFT) - 1)) == 0); + assert((end & ((1u << PSXM_SHIFT) - 1)) == 0); + + for (i = start; i < end; i += (1u << PSXM_SHIFT)) + lut[i >> PSXM_SHIFT] = (uintptr_t)mem - (i & ~(size - 1)); +} + +// shouldn't this affect reads, more mirrors? +static void mapRam(int isMapped) +{ + //uintptr_t *rLUT = psxRegs.ptrs.memRLUT; + uintptr_t *wLUT = psxRegs.ptrs.memWLUT; + + if (isMapped) { + u8 *ram = psxRegs.ptrs.psxM; + u32 i; + for (i = 0; i < 0x800000; i += 0x200000) { + lutMap(wLUT, ram, 0x200000, 0x00000000u + i, 0x00200000u + i); + lutMap(wLUT, ram, 0x200000, 0x80000000u + i, 0x80200000u + i); + lutMap(wLUT, ram, 0x200000, 0xa0000000u + i, 0xa0200000u + i); + } + } + else { + size_t len = (0x200000 >> PSXM_SHIFT) * sizeof(wLUT[0]); + //memset(rLUT + (0x00000000 >> PSXM_SHIFT), INVALID_PTR_VAL, len); + //memset(rLUT + (0x80000000 >> PSXM_SHIFT), INVALID_PTR_VAL, len); + //memset(rLUT + (0xa0000000 >> PSXM_SHIFT), INVALID_PTR_VAL, len); + memset(wLUT + (0x00000000 >> PSXM_SHIFT), INVALID_PTR_VAL, len); + memset(wLUT + (0x80000000 >> PSXM_SHIFT), INVALID_PTR_VAL, len); + //memset(wLUT + (0xa0000000 >> PSXM_SHIFT), INVALID_PTR_VAL, len); + } } int psxMemInit(void) { + size_t table_size = 1ul << (32 - PSXM_SHIFT); + uintptr_t *memRLUT; + uintptr_t *memWLUT; unsigned int i; int ret; @@ -214,44 +250,38 @@ int psxMemInit(void) if (DISABLE_MEM_LUTS) return 0; - psxMemRLUT = (u8 **)malloc(0x10000 * sizeof(void *)); - psxMemWLUT = (u8 **)malloc(0x10000 * sizeof(void *)); - - if (psxMemRLUT == NULL || psxMemWLUT == NULL) { + memRLUT = malloc(table_size * sizeof(memRLUT[0]) * 2); + if (memRLUT == NULL) { SysMessage("Error allocating psxMem LUTs"); psxMemShutdown(); return -1; } - memset(psxMemRLUT, (int)(uintptr_t)INVALID_PTR, 0x10000 * sizeof(void *)); - memset(psxMemWLUT, (int)(uintptr_t)INVALID_PTR, 0x10000 * sizeof(void *)); - -// MemR - for (i = 0; i < 0x80; i++) psxMemRLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16]; - - memcpy(psxMemRLUT + 0x8000, psxMemRLUT, 0x80 * sizeof(void *)); - memcpy(psxMemRLUT + 0xa000, psxMemRLUT, 0x80 * sizeof(void *)); - - psxMemRLUT[0x1f00] = (u8 *)psxP; - psxMemRLUT[0x1f80] = (u8 *)psxH; - - for (i = 0; i < 0x08; i++) psxMemRLUT[i + 0x1fc0] = (u8 *)&psxR[i << 16]; - - memcpy(psxMemRLUT + 0x9fc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *)); - memcpy(psxMemRLUT + 0xbfc0, psxMemRLUT + 0x1fc0, 0x08 * sizeof(void *)); - -// MemW - for (i = 0; i < 0x80; i++) psxMemWLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16]; + assert((s8)INVALID_PTR_VAL == INVALID_PTR_VAL); + memset(memRLUT, INVALID_PTR_VAL, table_size * sizeof(memRLUT[0]) * 2); + memWLUT = memRLUT + table_size; + psxRegs.ptrs.memRLUT = memRLUT; + psxRegs.ptrs.memWLUT = memWLUT; + + // ram + for (i = 0; i < 0x800000; i += 0x200000) { + u8 *ram = psxRegs.ptrs.psxM; + lutMap(memRLUT, ram, 0x200000, 0x00000000u + i, 0x00200000u + i); + lutMap(memRLUT, ram, 0x200000, 0x80000000u + i, 0x80200000u + i); + lutMap(memRLUT, ram, 0x200000, 0xa0000000u + i, 0xa0200000u + i); + } + mapRam(1); - memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *)); - memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *)); + // bios + lutMap(memRLUT, psxRegs.ptrs.psxR, 0x80000, 0x1fc00000u, 0x1fc80000u); + lutMap(memRLUT, psxRegs.ptrs.psxR, 0x80000, 0x9fc00000u, 0x9fc80000u); + lutMap(memRLUT, psxRegs.ptrs.psxR, 0x80000, 0xbfc00000u, 0xbfc80000u); // Don't allow writes to PIO Expansion region (psxP) to take effect. // NOTE: Not sure if this is needed to fix any games but seems wise, // seeing as some games do read from PIO as part of copy-protection // check. (See fix in psxMemReset() regarding psxP region reads). - psxMemWLUT[0x1f00] = INVALID_PTR; - psxMemWLUT[0x1f80] = (u8 *)psxH; + //memWLUT[0x1f000000 >> PSXM_SHIFT] = INVALID_PTR_VAL; return 0; } @@ -260,8 +290,11 @@ void psxMemReset() { FILE *f = NULL; char bios[1024]; - memset(psxM, 0, 0x00200000); - memset(psxP, 0xff, 0x00010000); + memset(psxRegs.ptrs.psxM, 0, 0x00200000); + memset(psxRegs.ptrs.psxP, 0xff, 0x00010000); + + if (!DISABLE_MEM_LUTS) + mapRam(1); Config.HLE = TRUE; @@ -272,7 +305,7 @@ void psxMemReset() { if (f == NULL) { SysMessage(_("Could not open BIOS:\"%s\". Enabling HLE Bios!\n"), bios); } else { - if (fread(psxR, 1, 0x80000, f) == 0x80000) { + if (fread(psxRegs.ptrs.psxR, 1, 0x80000, f) == 0x80000) { Config.HLE = FALSE; } else { SysMessage(_("The selected BIOS:\"%s\" is of wrong size. Enabling HLE Bios!\n"), bios); @@ -281,7 +314,7 @@ void psxMemReset() { } } if (Config.HLE) - memset(psxR, 0, 0x80000); + memset(psxRegs.ptrs.psxR, 0, 0x80000); } void psxMemShutdown() { @@ -290,8 +323,9 @@ void psxMemShutdown() { else psxMemFreeMap(); - free(psxMemRLUT); psxMemRLUT = NULL; - free(psxMemWLUT); psxMemWLUT = NULL; + free(psxRegs.ptrs.memRLUT); + psxRegs.ptrs.memRLUT = NULL; + psxRegs.ptrs.memWLUT = NULL; } int cache_isolated; @@ -299,17 +333,7 @@ int cache_isolated; void psxMemOnIsolate(int enable) { if (!DISABLE_MEM_LUTS) { - if (enable) { - memset(psxMemWLUT + 0x0000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *)); - memset(psxMemWLUT + 0x8000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *)); - //memset(psxMemWLUT + 0xa000, (int)(uintptr_t)INVALID_PTR, 0x80 * sizeof(void *)); - } else { - int i; - for (i = 0; i < 0x80; i++) - psxMemWLUT[i + 0x0000] = (void *)&psxM[(i & 0x1f) << 16]; - memcpy(psxMemWLUT + 0x8000, psxMemWLUT, 0x80 * sizeof(void *)); - memcpy(psxMemWLUT + 0xa000, psxMemWLUT, 0x80 * sizeof(void *)); - } + mapRam(!enable); } cache_isolated = enable; @@ -317,184 +341,129 @@ void psxMemOnIsolate(int enable) : R3000ACPU_NOTIFY_CACHE_UNISOLATED, NULL); } -u8 psxMemRead8(u32 mem) { - char *p; +u8 psxMemRead8(psxRegisters *regs, u32 mem) { + u8 *p; u32 t; + if (likely(psxm_(&p, regs, mem, 0))) + return *p; + t = mem >> 16; if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { if ((mem & 0xffff) < 0x400) - return psxHu8(mem); + return regs->ptrs.psxH[mem & 0x3ff]; else return psxHwRead8(mem); - } else { - p = psxm(mem, 0); - if (p != INVALID_PTR) { - if (Config.Debug) - DebugCheckBP((mem & 0xffffff) | 0x80000000, R1); - return *(u8 *)p; - } else { -#ifdef PSXMEM_LOG - PSXMEM_LOG("err lb %8.8lx\n", mem); -#endif - return 0xFF; - } } + return 0xFF; } -u16 psxMemRead16(u32 mem) { - char *p; +u16 psxMemRead16(psxRegisters *regs, u32 mem) { + u8 *p; u32 t; + if (likely(psxm_(&p, regs, mem, 0))) + return SWAPu16(*(u16 *)p); + t = mem >> 16; if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { if ((mem & 0xffff) < 0x400) - return psxHu16(mem); + return SWAPu16(*(u16 *)(regs->ptrs.psxH + (mem & 0x3fe))); else return psxHwRead16(mem); - } else { - p = psxm(mem, 0); - if (p != INVALID_PTR) { - if (Config.Debug) - DebugCheckBP((mem & 0xffffff) | 0x80000000, R2); - return SWAPu16(*(u16 *)p); - } else { -#ifdef PSXMEM_LOG - PSXMEM_LOG("err lh %8.8lx\n", mem); -#endif - return 0xFFFF; - } } + return 0xFFFF; } -u32 psxMemRead32(u32 mem) { - char *p; +u32 psxMemRead32(psxRegisters *regs, u32 mem) { + u8 *p; u32 t; + if (likely(psxm_(&p, regs, mem, 0))) + return SWAPu32(*(u32 *)p); + t = mem >> 16; if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { if ((mem & 0xffff) < 0x400) - return psxHu32(mem); + return SWAPu32(*(u32 *)(regs->ptrs.psxH + (mem & 0x3fc))); else return psxHwRead32(mem); - } else { - p = psxm(mem, 0); - if (p != INVALID_PTR) { - if (Config.Debug) - DebugCheckBP((mem & 0xffffff) | 0x80000000, R4); - return SWAPu32(*(u32 *)p); - } else { - if (mem == 0xfffe0130) - return psxRegs.biuReg; -#ifdef PSXMEM_LOG - PSXMEM_LOG("err lw %8.8lx\n", mem); -#endif - return 0xFFFFFFFF; - } } + if (mem == 0xfffe0130) + return regs->biuReg; + return 0xFFFFFFFF; } -void psxMemWrite8(u32 mem, u32 value) { - char *p; +void psxMemWrite8(psxRegisters *regs, u32 mem, u32 value) { + u8 *p; u32 t; + if (likely(psxm_(&p, regs, mem, 1))) { + *p = value; +#ifndef DRC_DISABLE + psxCpu->Clear(mem & ~3, 1); +#endif + return; + } + t = mem >> 16; if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { if ((mem & 0xffff) < 0x400) - psxHu8(mem) = value; + regs->ptrs.psxH[mem & 0x3ff] = value; else psxHwWrite8(mem, value); - } else { - p = psxm(mem, 1); - if (p != INVALID_PTR) { - if (Config.Debug) - DebugCheckBP((mem & 0xffffff) | 0x80000000, W1); - *(u8 *)p = value; -#ifndef DRC_DISABLE - psxCpu->Clear((mem & (~3)), 1); -#endif - } else { -#ifdef PSXMEM_LOG - PSXMEM_LOG("err sb %8.8lx\n", mem); -#endif - } + return; } + log_unhandled("unhandled w8 %08x %08x @%08x\n", mem, value, regs->pc); } -void psxMemWrite16(u32 mem, u32 value) { - char *p; +void psxMemWrite16(psxRegisters *regs, u32 mem, u32 value) { + u8 *p; u32 t; + if (likely(psxm_(&p, regs, mem, 1))) { + *(u16 *)p = SWAPu16(value); +#ifndef DRC_DISABLE + psxCpu->Clear(mem & ~3, 1); +#endif + return; + } + t = mem >> 16; if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { if ((mem & 0xffff) < 0x400) - psxHu16ref(mem) = SWAPu16(value); + *(u16 *)(regs->ptrs.psxH + (mem & 0x3fe)) = SWAPu16(value); else psxHwWrite16(mem, value); - } else { - p = psxm(mem, 1); - if (p != INVALID_PTR) { - if (Config.Debug) - DebugCheckBP((mem & 0xffffff) | 0x80000000, W2); - *(u16 *)p = SWAPu16(value); -#ifndef DRC_DISABLE - psxCpu->Clear((mem & (~3)), 1); -#endif - } else { -#ifdef PSXMEM_LOG - PSXMEM_LOG("err sh %8.8lx\n", mem); -#endif - } + return; } + log_unhandled("unhandled w16 %08x %08x @%08x\n", mem, value, regs->pc); } -void psxMemWrite32(u32 mem, u32 value) { - char *p; +void psxMemWrite32(psxRegisters *regs, u32 mem, u32 value) { + u8 *p; u32 t; -// if ((mem&0x1fffff) == 0x71E18 || value == 0x48088800) SysPrintf("t2fix!!\n"); - t = mem >> 16; - if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { - if ((mem & 0xffff) < 0x400) - psxHu32ref(mem) = SWAPu32(value); - else - psxHwWrite32(mem, value); - } else { - p = psxm(mem, 1); - if (p != INVALID_PTR) { - if (Config.Debug) - DebugCheckBP((mem & 0xffffff) | 0x80000000, W4); - *(u32 *)p = SWAPu32(value); + if (likely(psxm_(&p, regs, mem, 1))) { + *(u32 *)p = SWAPu32(value); #ifndef DRC_DISABLE - psxCpu->Clear(mem, 1); + psxCpu->Clear(mem & ~3, 1); #endif - } else { - if (mem == 0xfffe0130) { - psxRegs.biuReg = value; - return; - } -#ifdef PSXMEM_LOG - PSXMEM_LOG("err sw %8.8lx\n", mem); -#endif - } + return; } -} - -void *psxMemPointer(u32 mem) { - char *p; - u32 t; t = mem >> 16; if (t == 0x1f80 || t == 0x9f80 || t == 0xbf80) { if ((mem & 0xffff) < 0x400) - return (void *)&psxH[mem]; + *(u32 *)(regs->ptrs.psxH + (mem & 0x3fc)) = SWAPu32(value); else - return NULL; - } else { - p = psxm(mem, 1); - if (p != INVALID_PTR) { - return (void *)p; - } - return NULL; + psxHwWrite32(mem, value); + return; + } + if (mem == 0xfffe0130) { + regs->biuReg = value; + return; } + if (!(regs->CP0.n.SR & ((1u << 16)))) + log_unhandled("unhandled w32 %08x %08x @%08x\n", mem, value, regs->pc); } diff --git a/libpcsxcore/psxmem.h b/libpcsxcore/psxmem.h index f9cc8f0c..5fb0e103 100644 --- a/libpcsxcore/psxmem.h +++ b/libpcsxcore/psxmem.h @@ -25,6 +25,7 @@ extern "C" { #endif #include "psxcommon.h" +#include "r3000a.h" #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ @@ -46,87 +47,53 @@ extern "C" { #endif +// this is needed because: +// - lighrec sometimes maps ram at address 0 +// - memRLUT[] may contain 0 as a valid entry +#define INVALID_PTR_VAL -1l #ifdef LIGHTREC -#define INVALID_PTR ((void *)-1) +#define INVALID_PTR ((void *)INVALID_PTR_VAL) #else #define INVALID_PTR NULL #endif -extern s8 *psxM; -#define psxMs8(mem) psxM[(mem) & 0x1fffff] -#define psxMs16(mem) (SWAP16(*(s16 *)&psxM[(mem) & 0x1fffff])) -#define psxMs32(mem) (SWAP32(*(s32 *)&psxM[(mem) & 0x1fffff])) -#define psxMu8(mem) (*(u8 *)&psxM[(mem) & 0x1fffff]) -#define psxMu16(mem) (SWAP16(*(u16 *)&psxM[(mem) & 0x1fffff])) -#define psxMu32(mem) (SWAP32(*(u32 *)&psxM[(mem) & 0x1fffff])) - -#define psxMs8ref(mem) psxM[(mem) & 0x1fffff] -#define psxMs16ref(mem) (*(s16 *)&psxM[(mem) & 0x1fffff]) -#define psxMs32ref(mem) (*(s32 *)&psxM[(mem) & 0x1fffff]) -#define psxMu8ref(mem) (*(u8 *)&psxM[(mem) & 0x1fffff]) -#define psxMu16ref(mem) (*(u16 *)&psxM[(mem) & 0x1fffff]) -#define psxMu32ref(mem) (*(u32 *)&psxM[(mem) & 0x1fffff]) - -extern s8 *psxP; -#define psxPs8(mem) psxP[(mem) & 0xffff] -#define psxPs16(mem) (SWAP16(*(s16 *)&psxP[(mem) & 0xffff])) -#define psxPs32(mem) (SWAP32(*(s32 *)&psxP[(mem) & 0xffff])) -#define psxPu8(mem) (*(u8 *)&psxP[(mem) & 0xffff]) -#define psxPu16(mem) (SWAP16(*(u16 *)&psxP[(mem) & 0xffff])) -#define psxPu32(mem) (SWAP32(*(u32 *)&psxP[(mem) & 0xffff])) - -#define psxPs8ref(mem) psxP[(mem) & 0xffff] -#define psxPs16ref(mem) (*(s16 *)&psxP[(mem) & 0xffff]) -#define psxPs32ref(mem) (*(s32 *)&psxP[(mem) & 0xffff]) -#define psxPu8ref(mem) (*(u8 *)&psxP[(mem) & 0xffff]) -#define psxPu16ref(mem) (*(u16 *)&psxP[(mem) & 0xffff]) -#define psxPu32ref(mem) (*(u32 *)&psxP[(mem) & 0xffff]) - -extern s8 *psxR; -#define psxRs8(mem) psxR[(mem) & 0x7ffff] -#define psxRs16(mem) (SWAP16(*(s16 *)&psxR[(mem) & 0x7ffff])) -#define psxRs32(mem) (SWAP32(*(s32 *)&psxR[(mem) & 0x7ffff])) -#define psxRu8(mem) (*(u8* )&psxR[(mem) & 0x7ffff]) -#define psxRu16(mem) (SWAP16(*(u16 *)&psxR[(mem) & 0x7ffff])) -#define psxRu32(mem) (SWAP32(*(u32 *)&psxR[(mem) & 0x7ffff])) - -#define psxRs8ref(mem) psxR[(mem) & 0x7ffff] -#define psxRs16ref(mem) (*(s16*)&psxR[(mem) & 0x7ffff]) -#define psxRs32ref(mem) (*(s32*)&psxR[(mem) & 0x7ffff]) -#define psxRu8ref(mem) (*(u8 *)&psxR[(mem) & 0x7ffff]) -#define psxRu16ref(mem) (*(u16*)&psxR[(mem) & 0x7ffff]) -#define psxRu32ref(mem) (*(u32*)&psxR[(mem) & 0x7ffff]) - -extern s8 *psxH; -#define psxHs8(mem) psxH[(mem) & 0xffff] -#define psxHs16(mem) (SWAP16(*(s16 *)&psxH[(mem) & 0xffff])) -#define psxHs32(mem) (SWAP32(*(s32 *)&psxH[(mem) & 0xffff])) -#define psxHu8(mem) (*(u8 *)&psxH[(mem) & 0xffff]) -#define psxHu16(mem) (SWAP16(*(u16 *)&psxH[(mem) & 0xffff])) -#define psxHu32(mem) (SWAP32(*(u32 *)&psxH[(mem) & 0xffff])) - -#define psxHs8ref(mem) psxH[(mem) & 0xffff] -#define psxHs16ref(mem) (*(s16 *)&psxH[(mem) & 0xffff]) -#define psxHs32ref(mem) (*(s32 *)&psxH[(mem) & 0xffff]) -#define psxHu8ref(mem) (*(u8 *)&psxH[(mem) & 0xffff]) -#define psxHu16ref(mem) (*(u16 *)&psxH[(mem) & 0xffff]) -#define psxHu32ref(mem) (*(u32 *)&psxH[(mem) & 0xffff]) - -extern u8 **psxMemWLUT; -extern u8 **psxMemRLUT; +#define PSXM_SHIFT 19 + +#define psxMu8(mem) (*(u8 *)&psxRegs.ptrs.psxM[(mem) & 0x1fffff]) +#define psxMu16(mem) (SWAP16(*(u16 *)&psxRegs.ptrs.psxM[(mem) & 0x1fffff])) +#define psxMu32(mem) (SWAP32(*(u32 *)&psxRegs.ptrs.psxM[(mem) & 0x1fffff])) + +#define psxMu8ref(mem) (*(u8 *)&psxRegs.ptrs.psxM[(mem) & 0x1fffff]) +#define psxMu16ref(mem) (*(u16 *)&psxRegs.ptrs.psxM[(mem) & 0x1fffff]) +#define psxMu32ref(mem) (*(u32 *)&psxRegs.ptrs.psxM[(mem) & 0x1fffff]) + +#define psxHu8(mem) (*(u8 *)&psxRegs.ptrs.psxH[(mem) & 0xffff]) +#define psxHu16(mem) (SWAP16(*(u16 *)&psxRegs.ptrs.psxH[(mem) & 0xffff])) +#define psxHu32(mem) (SWAP32(*(u32 *)&psxRegs.ptrs.psxH[(mem) & 0xffff])) + +#define psxHu8ref(mem) (*(u8 *)&psxRegs.ptrs.psxH[(mem) & 0xffff]) +#define psxHu16ref(mem) (*(u16 *)&psxRegs.ptrs.psxH[(mem) & 0xffff]) +#define psxHu32ref(mem) (*(u32 *)&psxRegs.ptrs.psxH[(mem) & 0xffff]) + extern int cache_isolated; #ifndef DISABLE_MEM_LUTS #define DISABLE_MEM_LUTS 0 #endif -static inline void * psxm_lut(u32 mem, int write, u8 **lut) +// it may seem returning the pointer would be convenient here, +// but that causes double compare (after lut and after ptr arithmetic), +// and this is a hot path for the interpreter and non-dynarec-allowing systems, like apple +static inline int psxm_lut(u8 **ret, const psxRegisters *regs, u32 mem, int write, + const uintptr_t *lut) { if (!DISABLE_MEM_LUTS) { - void *ptr = lut[mem >> 16]; - - return ptr == INVALID_PTR ? INVALID_PTR - : (void *)((uintptr_t)ptr + (u16)mem); + uintptr_t ptr = lut[mem >> PSXM_SHIFT]; + if (ptr != INVALID_PTR_VAL) { + *ret = (u8 *)(ptr + mem); + return 1; + } + return 0; } if (mem >= 0xa0000000) @@ -134,54 +101,56 @@ static inline void * psxm_lut(u32 mem, int write, u8 **lut) else mem &= ~0x80000000; - if (mem < 0x800000) { - if (cache_isolated) - return INVALID_PTR; + if (mem < 0x800000u) { + if (write && cache_isolated) + return 0; - return &psxM[mem & 0x1fffff]; + *ret = regs->ptrs.psxM + (mem & 0x1fffff); + return 1; } - if (mem > 0x1f800000 && mem <= 0x1f810000) - return &psxH[mem - 0x1f800000]; - - if (!write) { - if (mem > 0x1fc00000 && mem <= 0x1fc80000) - return &psxR[mem - 0x1fc00000]; - - if (mem > 0x1f000000 && mem <= 0x1f010000) - return &psxP[mem - 0x1f000000]; + if (!write && mem - 0x1fc00000u < 0x80000u) { + *ret = regs->ptrs.psxR + (mem - 0x1fc00000u); + return 1; } - return INVALID_PTR; + return 0; +} + +static inline int psxm_(u8 **ret, const psxRegisters *regs, u32 mem, int write) +{ + return psxm_lut(ret, regs, mem, write, + write ? regs->ptrs.memWLUT : regs->ptrs.memRLUT); } static inline void * psxm(u32 mem, int write) { - return psxm_lut(mem, write, write ? psxMemWLUT : psxMemRLUT); + u8 *ret; + if (psxm_(&ret, &psxRegs, mem, write)) + return ret; + return INVALID_PTR; } #define PSXM(mem) psxm(mem, 0) -#define PSXMs8(mem) (*(s8 *)PSXM(mem)) -#define PSXMs16(mem) (SWAP16(*(s16 *)PSXM(mem))) -#define PSXMs32(mem) (SWAP32(*(s32 *)PSXM(mem))) #define PSXMu8(mem) (*(u8 *)PSXM(mem)) #define PSXMu16(mem) (SWAP16(*(u16 *)PSXM(mem))) #define PSXMu32(mem) (SWAP32(*(u32 *)PSXM(mem))) #define PSXMu32ref(mem) (*(u32 *)PSXM(mem)) +struct psxRegisters; + int psxMemInit(); void psxMemReset(); void psxMemOnIsolate(int enable); void psxMemShutdown(); -u8 psxMemRead8 (u32 mem); -u16 psxMemRead16(u32 mem); -u32 psxMemRead32(u32 mem); -void psxMemWrite8 (u32 mem, u32 value); -void psxMemWrite16(u32 mem, u32 value); -void psxMemWrite32(u32 mem, u32 value); -void *psxMemPointer(u32 mem); +u8 psxMemRead8 (struct psxRegisters *regs, u32 mem); +u16 psxMemRead16(struct psxRegisters *regs, u32 mem); +u32 psxMemRead32(struct psxRegisters *regs, u32 mem); +void psxMemWrite8 (struct psxRegisters *regs, u32 mem, u32 value); +void psxMemWrite16(struct psxRegisters *regs, u32 mem, u32 value); +void psxMemWrite32(struct psxRegisters *regs, u32 mem, u32 value); #ifdef __cplusplus } diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index 3298b766..a25c01d4 100644 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -29,6 +29,7 @@ #include "psxbios.h" #include "psxevents.h" #include "../include/compiler_features.h" +#include #include #ifndef ARRAY_SIZE @@ -64,7 +65,7 @@ void psxReset() { psxMemReset(); - memset(&psxRegs, 0, sizeof(psxRegs)); + memset(&psxRegs, 0, offsetof(psxRegisters, ptrs)); psxRegs.pc = 0xbfc00000; // Start in bootstrap diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index df7882ce..1de1ebd5 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -26,6 +26,12 @@ extern "C" { #include "psxcommon.h" +#ifdef __i386__ +#define INT_ATTR __attribute__((regparm(2))) +#else +#define INT_ATTR +#endif + enum R3000Aexception { R3000E_Int = 0, // Interrupt R3000E_AdEL = 4, // Address error (on load/I-fetch) @@ -217,9 +223,20 @@ typedef struct psxRegisters { u32 biosBranchCheck; u32 cpuInRecursion; u32 gpuIdleAfter; - u32 unused3[2]; // warning: changing anything in psxRegisters requires update of all // asm in libpcsxcore/new_dynarec/ and may break savestates + // ptrs must be last + struct { + u8 *psxM; // Kernel & User Memory (2 Meg) + u8 *psxP; // Parallel/Expansion Port (64K) (not used) + u8 *psxR; // BIOS ROM (512K) + u8 *psxH; // Scratch Pad (1K) & Hardware Registers (8K) + uintptr_t *memRLUT; + uintptr_t *memWLUT; + u32 (INT_ATTR *intFetch)(struct psxRegisters *regs_, + const uintptr_t *memRLUT, u32 pc); + void *unused3[3]; + } ptrs; } psxRegisters; extern psxRegisters psxRegs;