CFLAGS += -DPCNT
endif
+LIGHTREC_CUSTOM_MAP ?= 0
+
# core
OBJS += libpcsxcore/cdriso.o libpcsxcore/cdrom.o libpcsxcore/cheat.o libpcsxcore/database.o \
libpcsxcore/decode_xa.o libpcsxcore/mdec.o \
# dynarec
ifeq "$(DYNAREC)" "lightrec"
CFLAGS += -Ideps/lightning/include -Ideps/lightrec -Iinclude/lightning -Iinclude/lightrec \
- -DLIGHTREC -DLIGHTREC_STATIC
+ -DLIGHTREC -DLIGHTREC_STATIC \
+ -DLIGHTREC_CUSTOM_MAP=$(LIGHTREC_CUSTOM_MAP)
+LDLIBS += -lrt
+ifeq ($(LIGHTREC_CUSTOM_MAP),1)
+OBJS += libpcsxcore/lightrec/mem.o
+endif
OBJS += libpcsxcore/lightrec/plugin.o
OBJS += deps/lightning/lib/jit_disasm.o \
deps/lightning/lib/jit_memory.o \
deps/lightrec/regcache.o \
deps/lightrec/recompiler.o \
deps/lightrec/reaper.o
+libpcsxcore/lightrec/mem.o: CFLAGS += -D_GNU_SOURCE
ifeq ($(MMAP_WIN32),1)
CFLAGS += -Iinclude/mman
OBJS += deps/mman/mman.o
TARGET := $(TARGET_NAME)_libretro.so
fpic := -fPIC
THREAD_RENDERING = 1
+ifeq ($(shell uname),Linux)
+ LIGHTREC_CUSTOM_MAP := 1
+endif
ifneq ($(findstring SunOS,$(shell uname -s)),)
CC = gcc
endif
LIBDL :=
LIBM :=
NO_UNDEF_CHECK = 1
+ LIGHTREC_CUSTOM_MAP := 1
# OS X
else ifeq ($(platform), osx)
ptr = (u8 *)PSXM(madr);
- if (ptr == NULL) {
+ if (ptr == INVALID_PTR) {
CDR_LOG("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n");
break;
}
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2022 Paul Cercueil <paul@crapouillou.net>
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "../psxhw.h"
+#include "../psxmem.h"
+#include "../r3000a.h"
+
+#include "mem.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) ? (sizeof(a) / sizeof((a)[0])) : 0)
+
+#ifndef MAP_FIXED_NOREPLACE
+#define MAP_FIXED_NOREPLACE 0x100000
+#endif
+
+static const uintptr_t supported_io_bases[] = {
+ 0x0,
+ 0x10000000,
+ 0x40000000,
+ 0x80000000,
+};
+
+static void * mmap_huge(void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset)
+{
+ void *map = MAP_FAILED;
+
+ if (length >= 0x200000) {
+ map = mmap(addr, length, prot,
+ flags | MAP_HUGETLB | (21 << MAP_HUGE_SHIFT),
+ fd, offset);
+ if (map != MAP_FAILED)
+ printf("Hugetlb mmap to address 0x%lx succeeded\n", (uintptr_t) addr);
+ }
+
+ if (map == MAP_FAILED) {
+ map = mmap(addr, length, prot, flags, fd, offset);
+ if (map != MAP_FAILED)
+ printf("Regular mmap to address 0x%lx succeeded\n", (uintptr_t) addr);
+ }
+
+ return map;
+}
+
+static int lightrec_mmap_ram(bool hugetlb)
+{
+ unsigned int i, j;
+ int err, memfd, flags = 0;
+ uintptr_t base;
+ void *map;
+
+ if (hugetlb)
+ flags |= MFD_HUGETLB;
+
+ memfd = memfd_create("/lightrec_memfd", flags);
+ if (memfd < 0) {
+ err = -errno;
+ fprintf(stderr, "Failed to create memfd: %d\n", err);
+ return err;
+ }
+
+ err = ftruncate(memfd, 0x200000);
+ if (err < 0) {
+ err = -errno;
+ fprintf(stderr, "Could not trim memfd: %d\n", err);
+ goto err_close_memfd;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(supported_io_bases); i++) {
+ base = supported_io_bases[i];
+
+ for (j = 0; j < 4; j++) {
+ map = mmap_huge((void *)(base + j * 0x200000),
+ 0x200000, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED, memfd, 0);
+ if (map == MAP_FAILED)
+ break;
+ }
+
+ /* Impossible to map using this base */
+ if (j == 0)
+ continue;
+
+ /* All mirrors mapped - we got a match! */
+ if (j == 4)
+ break;
+
+ /* Only some mirrors mapped - clean the mess and try again */
+ for (; j > 0; j--)
+ munmap((void *)(base + (j - 1) * 0x200000), 0x200000);
+ }
+
+ if (i == ARRAY_SIZE(supported_io_bases)) {
+ err = -EINVAL;
+ goto err_close_memfd;
+ }
+
+ err = 0;
+ psxM = (s8 *)base;
+
+err_close_memfd:
+ close(memfd);
+ return err;
+}
+
+int lightrec_init_mmap(void)
+{
+ unsigned int i;
+ uintptr_t base;
+ void *map;
+ int err;
+
+ err = lightrec_mmap_ram(true);
+ if (err) {
+ err = lightrec_mmap_ram(false);
+ if (err) {
+ fprintf(stderr, "Unable to mmap RAM and mirrors\n");
+ return err;
+ }
+ }
+
+ base = (uintptr_t) psxM;
+
+ map = mmap((void *)(base + 0x1f000000), 0x10000,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED_NOREPLACE | MAP_ANONYMOUS, 0, 0);
+ if (map == MAP_FAILED) {
+ err = -EINVAL;
+ fprintf(stderr, "Unable to mmap parallel port\n");
+ goto err_unmap;
+ }
+
+ psxP = (s8 *)map;
+
+ map = mmap_huge((void *)(base + 0x1fc00000), 0x200000,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED_NOREPLACE | MAP_ANONYMOUS, 0, 0);
+ if (map == MAP_FAILED) {
+ err = -EINVAL;
+ fprintf(stderr, "Unable to mmap BIOS\n");
+ goto err_unmap_parallel;
+ }
+
+ psxR = (s8 *)map;
+
+ map = mmap((void *)(base + 0x1f800000), 0x10000,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED_NOREPLACE | MAP_ANONYMOUS, 0, 0);
+ if (map == MAP_FAILED) {
+ err = -EINVAL;
+ fprintf(stderr, "Unable to mmap scratchpad\n");
+ goto err_unmap_bios;
+ }
+
+ psxH = (s8 *)map;
+
+ return 0;
+
+err_unmap_bios:
+ munmap(psxR, 0x80000);
+err_unmap_parallel:
+ munmap(psxP, 0x10000);
+err_unmap:
+ for (i = 0; i < 4; i++)
+ munmap((void *)((uintptr_t)psxM + i * 0x200000), 0x200000);
+ return err;
+}
+
+void lightrec_free_mmap(void)
+{
+ unsigned int i;
+
+ munmap(psxH, 0x10000);
+ munmap(psxR, 0x80000);
+ munmap(psxP, 0x10000);
+ for (i = 0; i < 4; i++)
+ munmap((void *)((uintptr_t)psxM + i * 0x200000), 0x200000);
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022 Paul Cercueil <paul@crapouillou.net>
+ */
+
+#ifndef __LIGHTREC_MEM_H__
+#define __LIGHTREC_MEM_H__
+
+int lightrec_init_mmap(void);
+void lightrec_free_mmap(void);
+
+#endif /* __LIGHTREC_MEM_H__ */
lightrec_map[PSX_MAP_SCRATCH_PAD].address = psxH;
lightrec_map[PSX_MAP_PARALLEL_PORT].address = psxP;
+ 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_debug = !!getenv("LIGHTREC_DEBUG");
lightrec_very_debug = !!getenv("LIGHTREC_VERY_DEBUG");
use_lightrec_interpreter = !!getenv("LIGHTREC_INTERPRETER");
incTime();
READTRACK();
- if (ptr != NULL) memcpy(ptr, buf+12, 2048);
+ if (ptr != INVALID_PTR) memcpy(ptr, buf+12, 2048);
tmpHead.t_size -= 2048;
tmpHead.t_addr += 2048;
READTRACK();
mem = PSXM(addr);
- if (mem)
+ if (mem != INVALID_PTR)
memcpy(mem, buf + 12, 2048);
size -= 2048;
section_address = SWAP32(tmpHead.t_addr);
section_size = SWAP32(tmpHead.t_size);
mem = PSXM(section_address);
- if (mem != NULL) {
+ if (mem != INVALID_PTR) {
fseek(tmpFile, 0x800, SEEK_SET);
fread_to_ram(mem, section_size, 1, tmpFile);
psxCpu->Clear(section_address, section_size / 4);
EMU_LOG("Loading %08X bytes from %08X to %08X\n", section_size, ftell(tmpFile), section_address);
#endif
mem = PSXM(section_address);
- if (mem != NULL) {
+ if (mem != INVALID_PTR) {
fread_to_ram(mem, section_size, 1, tmpFile);
psxCpu->Clear(section_address, section_size / 4);
}
#endif
v0 = -1;
- if (pa1) {
+ if (pa1 != INVALID_PTR) {
switch (a0) {
case 2: buread(pa1, 1, 1); break;
case 3: buread(pa1, 2, 1); break;
PSXBIOS_LOG("psxBios_%s\n", biosA0n[0x09]);
#endif
v0 = -1;
- if (!pa1) {
+ if (pa1 == INVALID_PTR) {
pc0 = ra;
return;
}
void *psp;
psp = PSXM(sp);
- if (psp) {
+ if (psp != INVALID_PTR) {
memcpy(save, psp, 4 * 4);
psxMu32ref(sp) = SWAP32((u32)a0);
psxMu32ref(sp + 4) = SWAP32((u32)a1);
v0 = -1;
- if (pa0) {
+ if (pa0 != INVALID_PTR) {
if (!strncmp(pa0, "bu00", 4)) {
buopen(1, Mcd1Data, Config.Mcd1);
}
v0 = -1;
- if (pa1) {
+ if (pa1 != INVALID_PTR) {
switch (a0) {
case 2: buread(pa1, 1, a2); break;
case 3: buread(pa1, 2, a2); break;
#endif
v0 = -1;
- if (!pa1) {
+ if (pa1 == INVALID_PTR) {
pc0 = ra;
return;
}
v0 = 0;
- if (pa0) {
+ if (pa0 != INVALID_PTR) {
strcpy(ffile, pa0);
pfile = ffile+5;
nfile = 0;
v0 = 0;
- if (pa0 && pa1) {
+ if (pa0 != INVALID_PTR && pa1 != INVALID_PTR) {
if (!strncmp(pa0, "bu00", 4) && !strncmp(pa1, "bu00", 4)) {
burename(1);
}
v0 = 0;
- if (pa0) {
+ if (pa0 != INVALID_PTR) {
if (!strncmp(pa0, "bu00", 4)) {
budelete(1);
}
card_active_chan = a0;
port = a0 >> 4;
- if (pa2) {
+ if (pa2 != INVALID_PTR) {
if (port == 0) {
memcpy(Mcd1Data + a1 * 128, pa2, 128);
SaveMcd(Config.Mcd1, Mcd1Data, a1 * 128, 128);
card_active_chan = a0;
port = a0 >> 4;
- if (pa2) {
+ if (pa2 != INVALID_PTR) {
if (port == 0) {
memcpy(pa2, Mcd1Data + a1 * 128, 128);
} else {
PSXDMA_LOG("*** DMA4 SPU - mem2spu *** %x addr = %x size = %x\n", chcr, madr, bcr);
#endif
ptr = (u16 *)PSXM(madr);
- if (ptr == NULL) {
+ if (ptr == INVALID_PTR) {
#ifdef CPU_LOG
CPU_LOG("*** DMA4 SPU - mem2spu *** NULL Pointer!!!\n");
#endif
PSXDMA_LOG("*** DMA4 SPU - spu2mem *** %x addr = %x size = %x\n", chcr, madr, bcr);
#endif
ptr = (u16 *)PSXM(madr);
- if (ptr == NULL) {
+ if (ptr == INVALID_PTR) {
#ifdef CPU_LOG
CPU_LOG("*** DMA4 SPU - spu2mem *** NULL Pointer!!!\n");
#endif
PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
#endif
ptr = (u32 *)PSXM(madr);
- if (ptr == NULL) {
+ if (ptr == INVALID_PTR) {
#ifdef CPU_LOG
CPU_LOG("*** DMA2 GPU - vram2mem *** NULL Pointer!!!\n");
#endif
PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
#endif
ptr = (u32 *)PSXM(madr);
- if (ptr == NULL) {
+ if (ptr == INVALID_PTR) {
#ifdef CPU_LOG
CPU_LOG("*** DMA2 GPU - mem2vram *** NULL Pointer!!!\n");
#endif
#endif
if (chcr == 0x11000002) {
- if (mem == NULL) {
+ if (mem == INVALID_PTR) {
#ifdef CPU_LOG
CPU_LOG("*** DMA6 OT *** NULL Pointer!!!\n");
#endif
static u32 fetchNoCache(u32 pc)
{
u32 *code = (u32 *)PSXM(pc);
- return ((code == NULL) ? 0 : SWAP32(*code));
+ return ((code == INVALID_PTR) ? 0 : SWAP32(*code));
}
/*
if (((entry->tag ^ pc) & 0xfffffff0) != 0 || pc < entry->tag)
{
u32 *code = (u32 *)PSXM(pc & ~0x0f);
- if (!code)
+ if (code == INVALID_PTR)
return 0;
entry->tag = pc;
#include "psxhw.h"
#include "debug.h"
+#include "lightrec/mem.h"
#include "memmap.h"
#ifdef USE_LIBRETRO_VFS
if (psxMapHook != NULL) {
ret = psxMapHook(addr, size, 0, tag);
if (ret == NULL)
- return NULL;
+ return MAP_FAILED;
}
else {
/* avoid MAP_FIXED, it overrides existing mappings.. */
req = (void *)addr;
ret = mmap(req, size, PROT_READ | PROT_WRITE, flags, -1, 0);
if (ret == MAP_FAILED)
- return NULL;
+ return ret;
}
if (addr != 0 && ret != (void *)addr) {
if (is_fixed) {
psxUnmap(ret, size, tag);
- return NULL;
+ return MAP_FAILED;
}
if (((addr ^ (unsigned long)ret) & ~0xff000000l) && try_ < 2)
0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached
*/
-int psxMemInit() {
- int i;
-
- psxMemRLUT = (u8 **)malloc(0x10000 * sizeof(void *));
- psxMemWLUT = (u8 **)malloc(0x10000 * sizeof(void *));
- memset(psxMemRLUT, 0, 0x10000 * sizeof(void *));
- memset(psxMemWLUT, 0, 0x10000 * sizeof(void *));
-
+static int psxMemInitMap(void)
+{
psxM = psxMap(0x80000000, 0x00210000, 1, MAP_TAG_RAM);
- if (psxM == NULL)
+ if (psxM == MAP_FAILED)
psxM = psxMap(0x77000000, 0x00210000, 0, MAP_TAG_RAM);
- if (psxM == NULL) {
+ if (psxM == MAP_FAILED) {
SysMessage(_("mapping main RAM failed"));
return -1;
}
psxH = psxMap(0x1f800000, 0x10000, 0, MAP_TAG_OTHER);
psxR = psxMap(0x1fc00000, 0x80000, 0, MAP_TAG_OTHER);
- if (psxMemRLUT == NULL || psxMemWLUT == NULL ||
- psxR == NULL || psxP == NULL || psxH == NULL) {
+ if (psxR == MAP_FAILED || psxH == MAP_FAILED) {
SysMessage(_("Error allocating memory!"));
psxMemShutdown();
return -1;
}
+ return 0;
+}
+
+static void psxMemFreeMap(void)
+{
+ psxUnmap(psxM, 0x00210000, MAP_TAG_RAM); psxM = NULL;
+ psxUnmap(psxH, 0x10000, MAP_TAG_OTHER); psxH = NULL;
+ psxUnmap(psxR, 0x80000, MAP_TAG_OTHER); psxR = NULL;
+}
+
+int psxMemInit(void)
+{
+ unsigned int i;
+ int ret;
+
+ if (LIGHTREC_CUSTOM_MAP && Config.Cpu == CPU_DYNAREC)
+ ret = lightrec_init_mmap();
+ else
+ ret = psxMemInitMap();
+ if (ret) {
+ SysMessage(_("Error allocating memory!"));
+ psxMemShutdown();
+ return -1;
+ }
+
+ psxMemRLUT = (u8 **)malloc(0x10000 * sizeof(void *));
+ psxMemWLUT = (u8 **)malloc(0x10000 * sizeof(void *));
+
+ if (psxMemRLUT == NULL || psxMemWLUT == NULL) {
+ SysMessage(_("Error allocating memory!"));
+ psxMemShutdown();
+ return -1;
+ }
+
+ memset(psxMemRLUT, 0xff, 0x10000 * sizeof(void *));
+ memset(psxMemWLUT, 0xff, 0x10000 * sizeof(void *));
+
// MemR
for (i = 0; i < 0x80; i++) psxMemRLUT[i + 0x0000] = (u8 *)&psxM[(i & 0x1f) << 16];
// 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] = NULL;
+ psxMemWLUT[0x1f00] = INVALID_PTR;
psxMemWLUT[0x1f80] = (u8 *)psxH;
return 0;
}
void psxMemShutdown() {
- psxUnmap(psxM, 0x00210000, MAP_TAG_RAM); psxM = NULL;
- psxUnmap(psxH, 0x10000, MAP_TAG_OTHER); psxH = NULL;
- psxUnmap(psxR, 0x80000, MAP_TAG_OTHER); psxR = NULL;
+ if (LIGHTREC_CUSTOM_MAP && Config.Cpu == CPU_DYNAREC)
+ lightrec_free_mmap();
+ else
+ psxMemFreeMap();
free(psxMemRLUT); psxMemRLUT = NULL;
free(psxMemWLUT); psxMemWLUT = NULL;
return psxHwRead8(mem);
} else {
p = (char *)(psxMemRLUT[t]);
- if (p != NULL) {
+ if (p != INVALID_PTR) {
if (Config.Debug)
DebugCheckBP((mem & 0xffffff) | 0x80000000, R1);
return *(u8 *)(p + (mem & 0xffff));
return psxHwRead16(mem);
} else {
p = (char *)(psxMemRLUT[t]);
- if (p != NULL) {
+ if (p != INVALID_PTR) {
if (Config.Debug)
DebugCheckBP((mem & 0xffffff) | 0x80000000, R2);
return SWAPu16(*(u16 *)(p + (mem & 0xffff)));
return psxHwRead32(mem);
} else {
p = (char *)(psxMemRLUT[t]);
- if (p != NULL) {
+ if (p != INVALID_PTR) {
if (Config.Debug)
DebugCheckBP((mem & 0xffffff) | 0x80000000, R4);
return SWAPu32(*(u32 *)(p + (mem & 0xffff)));
psxHwWrite8(mem, value);
} else {
p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
+ if (p != INVALID_PTR) {
if (Config.Debug)
DebugCheckBP((mem & 0xffffff) | 0x80000000, W1);
*(u8 *)(p + (mem & 0xffff)) = value;
psxHwWrite16(mem, value);
} else {
p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
+ if (p != INVALID_PTR) {
if (Config.Debug)
DebugCheckBP((mem & 0xffffff) | 0x80000000, W2);
*(u16 *)(p + (mem & 0xffff)) = SWAPu16(value);
psxHwWrite32(mem, value);
} else {
p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
+ if (p != INVALID_PTR) {
if (Config.Debug)
DebugCheckBP((mem & 0xffffff) | 0x80000000, W4);
*(u32 *)(p + (mem & 0xffff)) = SWAPu32(value);
case 0x800: case 0x804:
if (writeok == 0) break;
writeok = 0;
- memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(void *));
- memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(void *));
- memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(void *));
+ memset(psxMemWLUT + 0x0000, 0xff, 0x80 * sizeof(void *));
+ memset(psxMemWLUT + 0x8000, 0xff, 0x80 * sizeof(void *));
+ memset(psxMemWLUT + 0xa000, 0xff, 0x80 * sizeof(void *));
/* Required for icache interpreter otherwise Armored Core won't boot on icache interpreter */
psxCpu->Notify(R3000ACPU_NOTIFY_CACHE_ISOLATED, NULL);
break;
return NULL;
} else {
p = (char *)(psxMemWLUT[t]);
- if (p != NULL) {
+ if (p != INVALID_PTR) {
return (void *)(p + (mem & 0xffff));
}
return NULL;
#endif
+#define INVALID_PTR ((void *)-1)
+
extern s8 *psxM;
#define psxMs8(mem) psxM[(mem) & 0x1fffff]
#define psxMs16(mem) (SWAP16(*(s16 *)&psxM[(mem) & 0x1fffff]))
extern u8 **psxMemWLUT;
extern u8 **psxMemRLUT;
-#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == 0 ? NULL : (u8*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)))
+#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == INVALID_PTR ? INVALID_PTR : (u8*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)))
#define PSXMs8(mem) (*(s8 *)PSXM(mem))
#define PSXMs16(mem) (SWAP16(*(s16 *)PSXM(mem)))
#define PSXMs32(mem) (SWAP32(*(s32 *)PSXM(mem)))
}
void psxShutdown() {
- psxMemShutdown();
psxBiosShutdown();
psxCpu->Shutdown();
+
+ psxMemShutdown();
}
void psxException(u32 code, u32 bd) {