vmem: no more 4GB vmem mode. only map elan RAM in naomi2 mode
Do not attempt to reserve 4GM of virtual space on 64-bit hosts. Use 512MB everywhere. Don't map elan RAM if not needed and dont protect/unprotect it in memwatch.
This commit is contained in:
parent
9069a49145
commit
32e3e7d9c5
|
@ -373,6 +373,7 @@ static void setPlatform(int platform)
|
||||||
{
|
{
|
||||||
if (VRAM_SIZE != 0)
|
if (VRAM_SIZE != 0)
|
||||||
_vmem_unprotect_vram(0, VRAM_SIZE);
|
_vmem_unprotect_vram(0, VRAM_SIZE);
|
||||||
|
elan::ERAM_SIZE = 0;
|
||||||
switch (platform)
|
switch (platform)
|
||||||
{
|
{
|
||||||
case DC_PLATFORM_DREAMCAST:
|
case DC_PLATFORM_DREAMCAST:
|
||||||
|
@ -395,6 +396,7 @@ static void setPlatform(int platform)
|
||||||
settings.platform.aram_size = 8 * 1024 * 1024;
|
settings.platform.aram_size = 8 * 1024 * 1024;
|
||||||
settings.platform.bios_size = 2 * 1024 * 1024;
|
settings.platform.bios_size = 2 * 1024 * 1024;
|
||||||
settings.platform.flash_size = 32 * 1024; // battery-backed ram
|
settings.platform.flash_size = 32 * 1024; // battery-backed ram
|
||||||
|
elan::ERAM_SIZE = 32 * 1024 * 1024;
|
||||||
break;
|
break;
|
||||||
case DC_PLATFORM_ATOMISWAVE:
|
case DC_PLATFORM_ATOMISWAVE:
|
||||||
settings.platform.ram_size = 16 * 1024 * 1024;
|
settings.platform.ram_size = 16 * 1024 * 1024;
|
||||||
|
|
|
@ -361,8 +361,7 @@ void _vmem_term()
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* virt_ram_base;
|
u8* virt_ram_base;
|
||||||
bool vmem_4gb_space;
|
static bool vmemAvailable = false;
|
||||||
static VMemType vmemstatus = MemTypeError;
|
|
||||||
|
|
||||||
static void *malloc_pages(size_t size)
|
static void *malloc_pages(size_t size)
|
||||||
{
|
{
|
||||||
|
@ -410,45 +409,24 @@ bool BM_LockedWrite(u8* address) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void _vmem_set_p0_mappings()
|
|
||||||
{
|
|
||||||
const vmem_mapping mem_mappings[] = {
|
|
||||||
// P0/U0
|
|
||||||
{0x00000000, 0x00800000, 0, 0, false}, // Area 0 -> unused
|
|
||||||
{0x00800000, 0x01000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
|
|
||||||
{0x01000000, 0x02800000, 0, 0, false}, // unused
|
|
||||||
{0x02800000, 0x03000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
|
|
||||||
{0x03000000, 0x04000000, 0, 0, false}, // unused
|
|
||||||
{0x04000000, 0x05000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
|
|
||||||
{0x05000000, 0x06000000, 0, 0, false}, // 32 bit path (unused)
|
|
||||||
{0x06000000, 0x07000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
|
|
||||||
{0x07000000, 0x08000000, 0, 0, false}, // 32 bit path (unused) mirror
|
|
||||||
{0x08000000, 0x0A000000, 0, 0, false}, // Area 2
|
|
||||||
{0x0A000000, 0x0C000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
|
|
||||||
{0x0C000000, 0x10000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
|
|
||||||
{0x10000000, 0x80000000, 0, 0, false}, // Area 4-7 (unused)
|
|
||||||
};
|
|
||||||
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _vmem_reserve()
|
bool _vmem_reserve()
|
||||||
{
|
{
|
||||||
static_assert((sizeof(Sh4RCB) % PAGE_SIZE) == 0, "sizeof(Sh4RCB) not multiple of PAGE_SIZE");
|
static_assert((sizeof(Sh4RCB) % PAGE_SIZE) == 0, "sizeof(Sh4RCB) not multiple of PAGE_SIZE");
|
||||||
|
|
||||||
if (vmemstatus != MemTypeError)
|
if (vmemAvailable)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Use vmem only if settings mandate so, and if we have proper exception handlers.
|
// Use vmem only if settings mandate so, and if we have proper exception handlers.
|
||||||
#if !defined(TARGET_NO_EXCEPTIONS)
|
#if !defined(TARGET_NO_EXCEPTIONS)
|
||||||
if (!settings.dynarec.disable_nvmem)
|
if (!settings.dynarec.disable_nvmem)
|
||||||
vmemstatus = vmem_platform_init((void**)&virt_ram_base, (void**)&p_sh4rcb, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX + elan::ELAN_RAM_SIZE);
|
vmemAvailable = vmem_platform_init((void**)&virt_ram_base, (void**)&p_sh4rcb, RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX + elan::ERAM_SIZE_MAX);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _vmem_term_mappings()
|
static void _vmem_term_mappings()
|
||||||
{
|
{
|
||||||
if (vmemstatus == MemTypeError)
|
if (!vmemAvailable)
|
||||||
{
|
{
|
||||||
free_pages(p_sh4rcb);
|
free_pages(p_sh4rcb);
|
||||||
p_sh4rcb = nullptr;
|
p_sh4rcb = nullptr;
|
||||||
|
@ -467,7 +445,7 @@ void _vmem_init_mappings()
|
||||||
{
|
{
|
||||||
_vmem_term_mappings();
|
_vmem_term_mappings();
|
||||||
// Fallback to statically allocated buffers, this results in slow-ops being generated.
|
// Fallback to statically allocated buffers, this results in slow-ops being generated.
|
||||||
if (vmemstatus == MemTypeError)
|
if (!vmemAvailable)
|
||||||
{
|
{
|
||||||
WARN_LOG(VMEM, "Warning! nvmem is DISABLED (due to failure or not being built-in");
|
WARN_LOG(VMEM, "Warning! nvmem is DISABLED (due to failure or not being built-in");
|
||||||
virt_ram_base = nullptr;
|
virt_ram_base = nullptr;
|
||||||
|
@ -488,94 +466,34 @@ void _vmem_init_mappings()
|
||||||
aica_ram.size = ARAM_SIZE;
|
aica_ram.size = ARAM_SIZE;
|
||||||
aica_ram.data = (u8*)malloc_pages(ARAM_SIZE);
|
aica_ram.data = (u8*)malloc_pages(ARAM_SIZE);
|
||||||
|
|
||||||
elan::RAM = (u8*)malloc_pages(elan::ELAN_RAM_SIZE);
|
elan::RAM = (u8*)malloc_pages(elan::ERAM_SIZE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NOTICE_LOG(VMEM, "Info: nvmem is enabled, with addr space of size %s", vmemstatus == MemType4GB ? "4GB" : "512MB");
|
NOTICE_LOG(VMEM, "Info: nvmem is enabled");
|
||||||
INFO_LOG(VMEM, "Info: p_sh4rcb: %p virt_ram_base: %p", p_sh4rcb, virt_ram_base);
|
INFO_LOG(VMEM, "Info: p_sh4rcb: %p virt_ram_base: %p", p_sh4rcb, virt_ram_base);
|
||||||
// Map the different parts of the memory file into the new memory range we got.
|
// Map the different parts of the memory file into the new memory range we got.
|
||||||
if (vmemstatus == MemType512MB)
|
const vmem_mapping mem_mappings[] = {
|
||||||
{
|
{0x00000000, 0x00800000, 0, 0, false}, // Area 0 -> unused
|
||||||
const vmem_mapping mem_mappings[] = {
|
{0x00800000, 0x01000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, false}, // Aica
|
||||||
{0x00000000, 0x00800000, 0, 0, false}, // Area 0 -> unused
|
{0x01000000, 0x04000000, 0, 0, false}, // More unused
|
||||||
{0x00800000, 0x01000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, false}, // Aica
|
{0x04000000, 0x05000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
|
||||||
{0x01000000, 0x04000000, 0, 0, false}, // More unused
|
{0x05000000, 0x06000000, 0, 0, false}, // 32 bit path (unused)
|
||||||
{0x04000000, 0x05000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
|
{0x06000000, 0x07000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
|
||||||
{0x05000000, 0x06000000, 0, 0, false}, // 32 bit path (unused)
|
{0x07000000, 0x08000000, 0, 0, false}, // 32 bit path (unused) mirror
|
||||||
{0x06000000, 0x07000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
|
{0x08000000, 0x0A000000, 0, 0, false}, // Area 2
|
||||||
{0x07000000, 0x08000000, 0, 0, false}, // 32 bit path (unused) mirror
|
{0x0A000000, 0x0C000000, MAP_ERAM_START_OFFSET, elan::ERAM_SIZE, true}, // Area 2 (Elan RAM)
|
||||||
{0x08000000, 0x0A000000, 0, 0, false}, // Area 2
|
{0x0C000000, 0x10000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
|
||||||
{0x0A000000, 0x0C000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
|
{0x10000000, 0x20000000, 0, 0, false}, // Area 4-7 (unused)
|
||||||
{0x0C000000, 0x10000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
|
// This is outside of the 512MB addr space. We map 8MB in all cases to help some games read past the end of aica ram
|
||||||
{0x10000000, 0x20000000, 0, 0, false}, // Area 4-7 (unused)
|
{0x20000000, 0x20800000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // writable aica ram
|
||||||
// This is outside of the 512MB addr space. We map 8MB in all cases to help some games read past the end of aica ram
|
};
|
||||||
{0x20000000, 0x20800000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // writable aica ram
|
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
|
||||||
};
|
|
||||||
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
|
|
||||||
|
|
||||||
// Point buffers to actual data pointers
|
// Point buffers to actual data pointers
|
||||||
aica_ram.data = &virt_ram_base[0x20000000]; // Points to the writable AICA addrspace
|
aica_ram.data = &virt_ram_base[0x20000000]; // Points to the writable AICA addrspace
|
||||||
vram.data = &virt_ram_base[0x04000000]; // Points to first vram mirror (writable and lockable)
|
vram.data = &virt_ram_base[0x04000000]; // Points to first vram mirror (writable and lockable)
|
||||||
mem_b.data = &virt_ram_base[0x0C000000]; // Main memory, first mirror
|
mem_b.data = &virt_ram_base[0x0C000000]; // Main memory, first mirror
|
||||||
elan::RAM = &virt_ram_base[0x0A000000];
|
elan::RAM = &virt_ram_base[0x0A000000];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_vmem_set_p0_mappings();
|
|
||||||
const vmem_mapping mem_mappings[] = {
|
|
||||||
// P1
|
|
||||||
{0x80000000, 0x80800000, 0, 0, false}, // Area 0 -> unused
|
|
||||||
{0x80800000, 0x81000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
|
|
||||||
{0x81000000, 0x82800000, 0, 0, false}, // unused
|
|
||||||
{0x82800000, 0x83000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
|
|
||||||
{0x83000000, 0x84000000, 0, 0, false}, // unused
|
|
||||||
{0x84000000, 0x85000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
|
|
||||||
{0x85000000, 0x86000000, 0, 0, false}, // 32 bit path (unused)
|
|
||||||
{0x86000000, 0x87000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
|
|
||||||
{0x87000000, 0x88000000, 0, 0, false}, // 32 bit path (unused) mirror
|
|
||||||
{0x88000000, 0x8A000000, 0, 0, false}, // Area 2
|
|
||||||
{0x8A000000, 0x8C000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
|
|
||||||
{0x8C000000, 0x90000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
|
|
||||||
{0x90000000, 0xA0000000, 0, 0, false}, // Area 4-7 (unused)
|
|
||||||
// P2
|
|
||||||
{0xA0000000, 0xA0800000, 0, 0, false}, // Area 0 -> unused
|
|
||||||
{0xA0800000, 0xA1000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
|
|
||||||
{0xA1000000, 0xA2800000, 0, 0, false}, // unused
|
|
||||||
{0xA2800000, 0xA3000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
|
|
||||||
{0xA3000000, 0xA4000000, 0, 0, false}, // unused
|
|
||||||
{0xA4000000, 0xA5000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
|
|
||||||
{0xA5000000, 0xA6000000, 0, 0, false}, // 32 bit path (unused)
|
|
||||||
{0xA6000000, 0xA7000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
|
|
||||||
{0xA7000000, 0xA8000000, 0, 0, false}, // 32 bit path (unused) mirror
|
|
||||||
{0xA8000000, 0xAA000000, 0, 0, false}, // Area 2
|
|
||||||
{0xAA000000, 0xAC000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
|
|
||||||
{0xAC000000, 0xB0000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
|
|
||||||
{0xB0000000, 0xC0000000, 0, 0, false}, // Area 4-7 (unused)
|
|
||||||
// P3
|
|
||||||
{0xC0000000, 0xC0800000, 0, 0, false}, // Area 0 -> unused
|
|
||||||
{0xC0800000, 0xC1000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica
|
|
||||||
{0xC1000000, 0xC2800000, 0, 0, false}, // unused
|
|
||||||
{0xC2800000, 0xC3000000, MAP_ARAM_START_OFFSET, ARAM_SIZE, true}, // Aica mirror
|
|
||||||
{0xC3000000, 0xC4000000, 0, 0, false}, // unused
|
|
||||||
{0xC4000000, 0xC5000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // Area 1 (vram, 16MB, wrapped on DC as 2x8MB)
|
|
||||||
{0xC5000000, 0xC6000000, 0, 0, false}, // 32 bit path (unused)
|
|
||||||
{0xC6000000, 0xC7000000, MAP_VRAM_START_OFFSET, VRAM_SIZE, true}, // VRAM mirror
|
|
||||||
{0xC7000000, 0xC8000000, 0, 0, false}, // 32 bit path (unused) mirror
|
|
||||||
{0xC8000000, 0xCA000000, 0, 0, false}, // Area 2
|
|
||||||
{0xCA000000, 0xCC000000, MAP_ERAM_START_OFFSET, elan::ELAN_RAM_SIZE, true}, // Area 2 (Elan RAM)
|
|
||||||
{0xCC000000, 0xD0000000, MAP_RAM_START_OFFSET, RAM_SIZE, true}, // Area 3 (main RAM + 3 mirrors)
|
|
||||||
{0xD0000000, 0x100000000L, 0, 0, false}, // Area 4-7 (unused)
|
|
||||||
};
|
|
||||||
vmem_platform_create_mappings(&mem_mappings[0], ARRAY_SIZE(mem_mappings));
|
|
||||||
|
|
||||||
// Point buffers to actual data pointers
|
|
||||||
aica_ram.data = &virt_ram_base[0x80800000]; // Points to the first AICA addrspace in P1
|
|
||||||
vram.data = &virt_ram_base[0x84000000]; // Points to first vram mirror (writable and lockable) in P1
|
|
||||||
mem_b.data = &virt_ram_base[0x8C000000]; // Main memory, first mirror in P1
|
|
||||||
elan::RAM = &virt_ram_base[0x8A000000];
|
|
||||||
|
|
||||||
vmem_4gb_space = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
aica_ram.size = ARAM_SIZE;
|
aica_ram.size = ARAM_SIZE;
|
||||||
vram.size = VRAM_SIZE;
|
vram.size = VRAM_SIZE;
|
||||||
|
@ -605,7 +523,7 @@ void _vmem_release()
|
||||||
_vmem_unprotect_vram(0, VRAM_SIZE);
|
_vmem_unprotect_vram(0, VRAM_SIZE);
|
||||||
_vmem_term_mappings();
|
_vmem_term_mappings();
|
||||||
}
|
}
|
||||||
vmemstatus = MemTypeError;
|
vmemAvailable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _vmem_protect_vram(u32 addr, u32 size)
|
void _vmem_protect_vram(u32 addr, u32 size)
|
||||||
|
@ -621,25 +539,6 @@ void _vmem_protect_vram(u32 addr, u32 size)
|
||||||
mem_region_lock(virt_ram_base + 0x04000000 + addr + VRAM_SIZE, size); // P0 wrap
|
mem_region_lock(virt_ram_base + 0x04000000 + addr + VRAM_SIZE, size); // P0 wrap
|
||||||
//mem_region_lock(virt_ram_base + 0x06000000 + addr + VRAM_SIZE, size); // P0 mirror wrap
|
//mem_region_lock(virt_ram_base + 0x06000000 + addr + VRAM_SIZE, size); // P0 mirror wrap
|
||||||
}
|
}
|
||||||
if (_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
mem_region_lock(virt_ram_base + 0x84000000 + addr, size); // P1
|
|
||||||
//mem_region_lock(virt_ram_base + 0x86000000 + addr, size); // P1 - mirror
|
|
||||||
mem_region_lock(virt_ram_base + 0xA4000000 + addr, size); // P2
|
|
||||||
//mem_region_lock(virt_ram_base + 0xA6000000 + addr, size); // P2 - mirror
|
|
||||||
// We should also lock P3 and its mirrors, but it doesn't seem to be used...
|
|
||||||
//mem_region_lock(virt_ram_base + 0xC4000000 + addr, size); // P3
|
|
||||||
//mem_region_lock(virt_ram_base + 0xC6000000 + addr, size); // P3 - mirror
|
|
||||||
if (VRAM_SIZE == 0x800000)
|
|
||||||
{
|
|
||||||
mem_region_lock(virt_ram_base + 0x84000000 + addr + VRAM_SIZE, size); // P1 wrap
|
|
||||||
//mem_region_lock(virt_ram_base + 0x86000000 + addr + VRAM_SIZE, size); // P1 - mirror wrap
|
|
||||||
mem_region_lock(virt_ram_base + 0xA4000000 + addr + VRAM_SIZE, size); // P2 wrap
|
|
||||||
//mem_region_lock(virt_ram_base + 0xA6000000 + addr + VRAM_SIZE, size); // P2 - mirror wrap
|
|
||||||
//mem_region_lock(virt_ram_base + 0xC4000000 + addr + VRAM_SIZE, size); // P3 wrap
|
|
||||||
//mem_region_lock(virt_ram_base + 0xC6000000 + addr + VRAM_SIZE, size); // P3 - mirror wrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -660,25 +559,6 @@ void _vmem_unprotect_vram(u32 addr, u32 size)
|
||||||
mem_region_unlock(virt_ram_base + 0x04000000 + addr + VRAM_SIZE, size); // P0 wrap
|
mem_region_unlock(virt_ram_base + 0x04000000 + addr + VRAM_SIZE, size); // P0 wrap
|
||||||
//mem_region_unlock(virt_ram_base + 0x06000000 + addr + VRAM_SIZE, size); // P0 mirror wrap
|
//mem_region_unlock(virt_ram_base + 0x06000000 + addr + VRAM_SIZE, size); // P0 mirror wrap
|
||||||
}
|
}
|
||||||
if (_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
mem_region_unlock(virt_ram_base + 0x84000000 + addr, size); // P1
|
|
||||||
//mem_region_unlock(virt_ram_base + 0x86000000 + addr, size); // P1 - mirror
|
|
||||||
mem_region_unlock(virt_ram_base + 0xA4000000 + addr, size); // P2
|
|
||||||
//mem_region_unlock(virt_ram_base + 0xA6000000 + addr, size); // P2 - mirror
|
|
||||||
// We should also lock P3 and its mirrors, but it doesn't seem to be used...
|
|
||||||
//mem_region_unlock(virt_ram_base + 0xC4000000 + addr, size); // P3
|
|
||||||
//mem_region_unlock(virt_ram_base + 0xC6000000 + addr, size); // P3 - mirror
|
|
||||||
if (VRAM_SIZE == 0x800000)
|
|
||||||
{
|
|
||||||
mem_region_unlock(virt_ram_base + 0x84000000 + addr + VRAM_SIZE, size); // P1 wrap
|
|
||||||
//mem_region_unlock(virt_ram_base + 0x86000000 + addr + VRAM_SIZE, size); // P1 - mirror wrap
|
|
||||||
mem_region_unlock(virt_ram_base + 0xA4000000 + addr + VRAM_SIZE, size); // P2 wrap
|
|
||||||
//mem_region_unlock(virt_ram_base + 0xA6000000 + addr + VRAM_SIZE, size); // P2 - mirror wrap
|
|
||||||
//mem_region_unlock(virt_ram_base + 0xC4000000 + addr + VRAM_SIZE, size); // P3 wrap
|
|
||||||
//mem_region_unlock(virt_ram_base + 0xC6000000 + addr + VRAM_SIZE, size); // P3 - mirror wrap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -691,21 +571,9 @@ u32 _vmem_get_vram_offset(void *addr)
|
||||||
if (_nvmem_enabled())
|
if (_nvmem_enabled())
|
||||||
{
|
{
|
||||||
ptrdiff_t offset = (u8*)addr - virt_ram_base;
|
ptrdiff_t offset = (u8*)addr - virt_ram_base;
|
||||||
if (_nvmem_4gb_space())
|
if (offset < 0 || offset >= 0x20000000)
|
||||||
{
|
|
||||||
if (offset < 0 || offset >= 0xE0000000)
|
|
||||||
return -1;
|
|
||||||
offset &= 0x1FFFFFFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (offset < 0 || offset >= 0x20000000)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((offset >> 24) != 4)
|
|
||||||
return -1;
|
return -1;
|
||||||
if ((((u8*)addr - virt_ram_base) >> 29) != 0 && (((u8*)addr - virt_ram_base) >> 29) != 4 && (((u8*)addr - virt_ram_base) >> 29) != 5)
|
if ((offset >> 24) != 4)
|
||||||
// other areas aren't mapped atm
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return offset & VRAM_MASK;
|
return offset & VRAM_MASK;
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
enum VMemType {
|
|
||||||
MemType4GB,
|
|
||||||
MemType512MB,
|
|
||||||
MemTypeError
|
|
||||||
};
|
|
||||||
|
|
||||||
struct vmem_mapping {
|
struct vmem_mapping {
|
||||||
u64 start_address, end_address;
|
u64 start_address, end_address;
|
||||||
u64 memoffset, memsize;
|
u64 memoffset, memsize;
|
||||||
|
@ -15,7 +9,7 @@ struct vmem_mapping {
|
||||||
|
|
||||||
// Platform specific vmemory API
|
// Platform specific vmemory API
|
||||||
// To initialize (maybe) the vmem subsystem
|
// To initialize (maybe) the vmem subsystem
|
||||||
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize);
|
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize);
|
||||||
// To reset the on-demand allocated pages.
|
// To reset the on-demand allocated pages.
|
||||||
void vmem_platform_reset_mem(void *ptr, unsigned size_bytes);
|
void vmem_platform_reset_mem(void *ptr, unsigned size_bytes);
|
||||||
// To handle a fault&allocate an ondemand page.
|
// To handle a fault&allocate an ondemand page.
|
||||||
|
@ -36,7 +30,7 @@ void vmem_platform_flush_cache(void *icache_start, void *icache_end, void *dcach
|
||||||
void vmem_platform_jit_set_exec(void* code, size_t size, bool enable);
|
void vmem_platform_jit_set_exec(void* code, size_t size, bool enable);
|
||||||
|
|
||||||
// Note: if you want to disable vmem magic in any given platform, implement the
|
// Note: if you want to disable vmem magic in any given platform, implement the
|
||||||
// above functions as empty functions and make vmem_platform_init return MemTypeError.
|
// above functions as empty functions and make vmem_platform_init return false.
|
||||||
|
|
||||||
//Typedef's
|
//Typedef's
|
||||||
//ReadMem
|
//ReadMem
|
||||||
|
@ -99,14 +93,10 @@ void* _vmem_read_const(u32 addr,bool& ismem,u32 sz);
|
||||||
void* _vmem_write_const(u32 addr,bool& ismem,u32 sz);
|
void* _vmem_write_const(u32 addr,bool& ismem,u32 sz);
|
||||||
|
|
||||||
extern u8* virt_ram_base;
|
extern u8* virt_ram_base;
|
||||||
extern bool vmem_4gb_space;
|
|
||||||
|
|
||||||
static inline bool _nvmem_enabled() {
|
static inline bool _nvmem_enabled() {
|
||||||
return virt_ram_base != 0;
|
return virt_ram_base != 0;
|
||||||
}
|
}
|
||||||
static inline bool _nvmem_4gb_space() {
|
|
||||||
return vmem_4gb_space;
|
|
||||||
}
|
|
||||||
void _vmem_bm_reset();
|
void _vmem_bm_reset();
|
||||||
|
|
||||||
void _vmem_protect_vram(u32 addr, u32 size);
|
void _vmem_protect_vram(u32 addr, u32 size);
|
||||||
|
|
|
@ -29,98 +29,30 @@ ElanRamWatcher elanWatcher;
|
||||||
void AicaRamWatcher::protectMem(u32 addr, u32 size)
|
void AicaRamWatcher::protectMem(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
size = std::min(ARAM_SIZE - addr, size) & ~PAGE_MASK;
|
size = std::min(ARAM_SIZE - addr, size) & ~PAGE_MASK;
|
||||||
if (_nvmem_enabled() && _nvmem_4gb_space()) {
|
mem_region_lock(aica_ram.data + addr,
|
||||||
mem_region_lock(virt_ram_base + 0x00800000 + addr, size); // P0
|
std::min(aica_ram.size - addr, size));
|
||||||
mem_region_lock(virt_ram_base + 0x02800000 + addr, size);// P0 - mirror
|
|
||||||
mem_region_lock(virt_ram_base + 0x80800000 + addr, size); // P1
|
|
||||||
//mem_region_lock(virt_ram_base + 0x82800000 + addr, size); // P1 - mirror
|
|
||||||
mem_region_lock(virt_ram_base + 0xA0800000 + addr, size); // P2
|
|
||||||
//mem_region_lock(virt_ram_base + 0xA2800000 + addr, size); // P2 - mirror
|
|
||||||
if (ARAM_SIZE == 2 * 1024 * 1024) {
|
|
||||||
mem_region_lock(virt_ram_base + 0x00A00000 + addr, size); // P0
|
|
||||||
mem_region_lock(virt_ram_base + 0x00C00000 + addr, size); // P0
|
|
||||||
mem_region_lock(virt_ram_base + 0x00E00000 + addr, size); // P0
|
|
||||||
mem_region_lock(virt_ram_base + 0x02A00000 + addr, size);// P0 - mirror
|
|
||||||
mem_region_lock(virt_ram_base + 0x02C00000 + addr, size);// P0 - mirror
|
|
||||||
mem_region_lock(virt_ram_base + 0x02E00000 + addr, size);// P0 - mirror
|
|
||||||
mem_region_lock(virt_ram_base + 0x80A00000 + addr, size); // P1
|
|
||||||
mem_region_lock(virt_ram_base + 0x80C00000 + addr, size); // P1
|
|
||||||
mem_region_lock(virt_ram_base + 0x80E00000 + addr, size); // P1
|
|
||||||
mem_region_lock(virt_ram_base + 0xA0A00000 + addr, size); // P2
|
|
||||||
mem_region_lock(virt_ram_base + 0xA0C00000 + addr, size); // P2
|
|
||||||
mem_region_lock(virt_ram_base + 0xA0E00000 + addr, size); // P2
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mem_region_lock(aica_ram.data + addr,
|
|
||||||
std::min(aica_ram.size - addr, size));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AicaRamWatcher::unprotectMem(u32 addr, u32 size)
|
void AicaRamWatcher::unprotectMem(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
size = std::min(ARAM_SIZE - addr, size) & ~PAGE_MASK;
|
size = std::min(ARAM_SIZE - addr, size) & ~PAGE_MASK;
|
||||||
if (_nvmem_enabled() && _nvmem_4gb_space()) {
|
mem_region_unlock(aica_ram.data + addr,
|
||||||
mem_region_unlock(virt_ram_base + 0x00800000 + addr, size); // P0
|
std::min(aica_ram.size - addr, size));
|
||||||
mem_region_unlock(virt_ram_base + 0x02800000 + addr, size); // P0 - mirror
|
|
||||||
mem_region_unlock(virt_ram_base + 0x80800000 + addr, size); // P1
|
|
||||||
//mem_region_unlock(virt_ram_base + 0x82800000 + addr, size); // P1 - mirror
|
|
||||||
mem_region_unlock(virt_ram_base + 0xA0800000 + addr, size); // P2
|
|
||||||
//mem_region_unlock(virt_ram_base + 0xA2800000 + addr, size); // P2 - mirror
|
|
||||||
if (ARAM_SIZE == 2 * 1024 * 1024) {
|
|
||||||
mem_region_unlock(virt_ram_base + 0x00A00000 + addr, size); // P0
|
|
||||||
mem_region_unlock(virt_ram_base + 0x00C00000 + addr, size); // P0
|
|
||||||
mem_region_unlock(virt_ram_base + 0x00E00000 + addr, size); // P0
|
|
||||||
mem_region_unlock(virt_ram_base + 0x02A00000 + addr, size); // P0 - mirror
|
|
||||||
mem_region_unlock(virt_ram_base + 0x02C00000 + addr, size); // P0 - mirror
|
|
||||||
mem_region_unlock(virt_ram_base + 0x02E00000 + addr, size); // P0 - mirror
|
|
||||||
mem_region_unlock(virt_ram_base + 0x80A00000 + addr, size); // P1
|
|
||||||
mem_region_unlock(virt_ram_base + 0x80C00000 + addr, size); // P1
|
|
||||||
mem_region_unlock(virt_ram_base + 0x80E00000 + addr, size); // P1
|
|
||||||
mem_region_unlock(virt_ram_base + 0xA0A00000 + addr, size); // P2
|
|
||||||
mem_region_unlock(virt_ram_base + 0xA0C00000 + addr, size); // P2
|
|
||||||
mem_region_unlock(virt_ram_base + 0xA0E00000 + addr, size); // P2
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mem_region_unlock(aica_ram.data + addr,
|
|
||||||
std::min(aica_ram.size - addr, size));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 AicaRamWatcher::getMemOffset(void *p)
|
u32 AicaRamWatcher::getMemOffset(void *p)
|
||||||
{
|
{
|
||||||
u32 addr;
|
if ((u8 *)p < &aica_ram[0] || (u8 *)p >= &aica_ram[ARAM_SIZE])
|
||||||
if (_nvmem_enabled() && _nvmem_4gb_space()) {
|
return -1;
|
||||||
if ((u8*) p < virt_ram_base || (u8*) p >= virt_ram_base + 0x100000000L)
|
return (u32)((u8 *)p - &aica_ram[0]);
|
||||||
return -1;
|
|
||||||
addr = (u32) ((u8*) p - virt_ram_base);
|
|
||||||
u32 area = (addr >> 29) & 7;
|
|
||||||
if (area != 0 && area != 4 && area != 5)
|
|
||||||
return -1;
|
|
||||||
addr &= 0x1fffffff & ~0x02000000;
|
|
||||||
if (addr < 0x00800000 || addr >= 0x01000000)
|
|
||||||
return -1;
|
|
||||||
addr &= ARAM_MASK;
|
|
||||||
} else {
|
|
||||||
if ((u8*) p < &aica_ram[0] || (u8*) p >= &aica_ram[ARAM_SIZE])
|
|
||||||
return -1;
|
|
||||||
addr = (u32) ((u8*) p - &aica_ram[0]);
|
|
||||||
}
|
|
||||||
return addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElanRamWatcher::protectMem(u32 addr, u32 size)
|
void ElanRamWatcher::protectMem(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
using namespace elan;
|
using namespace elan;
|
||||||
size = std::min(ELAN_RAM_SIZE - addr, size) & ~PAGE_MASK;
|
if (ERAM_SIZE != 0)
|
||||||
if (_nvmem_enabled())
|
|
||||||
{
|
{
|
||||||
mem_region_lock(virt_ram_base + 0x0a000000 + addr, size); // P0
|
size = std::min(ERAM_SIZE - addr, size) & ~PAGE_MASK;
|
||||||
if (_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
mem_region_lock(virt_ram_base + 0x8a000000 + addr, size); // P1
|
|
||||||
mem_region_lock(virt_ram_base + 0xaa000000 + addr, size); // P2
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mem_region_lock(RAM + addr, size);
|
mem_region_lock(RAM + addr, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,16 +60,9 @@ void ElanRamWatcher::protectMem(u32 addr, u32 size)
|
||||||
void ElanRamWatcher::unprotectMem(u32 addr, u32 size)
|
void ElanRamWatcher::unprotectMem(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
using namespace elan;
|
using namespace elan;
|
||||||
size = std::min(ELAN_RAM_SIZE - addr, size) & ~PAGE_MASK;
|
if (ERAM_SIZE != 0)
|
||||||
if (_nvmem_enabled())
|
|
||||||
{
|
{
|
||||||
mem_region_unlock(virt_ram_base + 0x0a000000 + addr, size); // P0
|
size = std::min(ERAM_SIZE - addr, size) & ~PAGE_MASK;
|
||||||
if (_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
mem_region_unlock(virt_ram_base + 0x8a000000 + addr, size); // P1
|
|
||||||
mem_region_unlock(virt_ram_base + 0xaa000000 + addr, size); // P2
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mem_region_unlock(RAM + addr, size);
|
mem_region_unlock(RAM + addr, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,25 +70,9 @@ void ElanRamWatcher::unprotectMem(u32 addr, u32 size)
|
||||||
u32 ElanRamWatcher::getMemOffset(void *p)
|
u32 ElanRamWatcher::getMemOffset(void *p)
|
||||||
{
|
{
|
||||||
using namespace elan;
|
using namespace elan;
|
||||||
u32 addr;
|
if ((u8 *)p < RAM || (u8 *)p >= &RAM[ERAM_SIZE])
|
||||||
if (_nvmem_enabled())
|
return -1;
|
||||||
{
|
return (u32)((u8 *)p - RAM);
|
||||||
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x100000000L)
|
|
||||||
return -1;
|
|
||||||
addr = (u32)((u8 *)p - virt_ram_base);
|
|
||||||
u32 area = (addr >> 29) & 7;
|
|
||||||
if (area != 0 && area != 4 && area != 5) // P0, P1 or P2 only
|
|
||||||
return -1;
|
|
||||||
addr &= 0x1fffffff;
|
|
||||||
if (addr < 0x0a000000 || addr >= 0x0a000000 + ELAN_RAM_SIZE)
|
|
||||||
return -1;
|
|
||||||
addr &= ELAN_RAM_MASK;
|
|
||||||
} else {
|
|
||||||
if ((u8 *)p < RAM || (u8 *)p >= &RAM[ELAN_RAM_SIZE])
|
|
||||||
return -1;
|
|
||||||
addr = (u32)((u8 *)p - RAM);
|
|
||||||
}
|
|
||||||
return addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,11 +69,14 @@
|
||||||
|
|
||||||
namespace elan {
|
namespace elan {
|
||||||
|
|
||||||
|
constexpr u32 ELAN_RAM_MASK = ERAM_SIZE_MAX - 1;
|
||||||
|
|
||||||
static _vmem_handler elanRegHandler;
|
static _vmem_handler elanRegHandler;
|
||||||
static _vmem_handler elanCmdHandler;
|
static _vmem_handler elanCmdHandler;
|
||||||
static _vmem_handler elanRamHandler;
|
static _vmem_handler elanRamHandler;
|
||||||
|
|
||||||
u8 *RAM;
|
u8 *RAM;
|
||||||
|
u32 ERAM_SIZE;
|
||||||
|
|
||||||
static u32 reg10;
|
static u32 reg10;
|
||||||
static u32 reg74;
|
static u32 reg74;
|
||||||
|
@ -478,7 +481,7 @@ struct State
|
||||||
|
|
||||||
static u32 elanRamAddress(void *p)
|
static u32 elanRamAddress(void *p)
|
||||||
{
|
{
|
||||||
if ((u8 *)p < RAM || (u8 *)p >= RAM + ELAN_RAM_SIZE)
|
if ((u8 *)p < RAM || (u8 *)p >= RAM + ERAM_SIZE)
|
||||||
return Null;
|
return Null;
|
||||||
else
|
else
|
||||||
return (u32)((u8 *)p - RAM);
|
return (u32)((u8 *)p - RAM);
|
||||||
|
@ -1441,7 +1444,7 @@ template<bool Active = true>
|
||||||
static void executeCommand(u8 *data, int size)
|
static void executeCommand(u8 *data, int size)
|
||||||
{
|
{
|
||||||
// verify(size >= 0);
|
// verify(size >= 0);
|
||||||
// verify(size < (int)ELAN_RAM_SIZE);
|
// verify(size < (int)ERAM_SIZE);
|
||||||
// if (0x2b00 == (u32)(data - RAM))
|
// if (0x2b00 == (u32)(data - RAM))
|
||||||
// for (int i = 0; i < size; i += 4)
|
// for (int i = 0; i < size; i += 4)
|
||||||
// DEBUG_LOG(PVR, "Elan Parse %08x: %08x", (u32)(&data[i] - RAM), *(u32 *)&data[i]);
|
// DEBUG_LOG(PVR, "Elan Parse %08x: %08x", (u32)(&data[i] - RAM), *(u32 *)&data[i]);
|
||||||
|
@ -1748,7 +1751,7 @@ void reset(bool hard)
|
||||||
{
|
{
|
||||||
if (hard)
|
if (hard)
|
||||||
{
|
{
|
||||||
memset(RAM, 0, ELAN_RAM_SIZE);
|
memset(RAM, 0, ERAM_SIZE);
|
||||||
state.reset();
|
state.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1780,7 +1783,7 @@ void serialize(Serializer& ser)
|
||||||
ser << reg74;
|
ser << reg74;
|
||||||
ser << elanCmd;
|
ser << elanCmd;
|
||||||
if (!ser.rollback())
|
if (!ser.rollback())
|
||||||
ser.serialize(RAM, ELAN_RAM_SIZE);
|
ser.serialize(RAM, ERAM_SIZE);
|
||||||
state.serialize(ser);
|
state.serialize(ser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1792,7 +1795,7 @@ void deserialize(Deserializer& deser)
|
||||||
deser >> reg74;
|
deser >> reg74;
|
||||||
deser >> elanCmd;
|
deser >> elanCmd;
|
||||||
if (!deser.rollback())
|
if (!deser.rollback())
|
||||||
deser.deserialize(RAM, ELAN_RAM_SIZE);
|
deser.deserialize(RAM, ERAM_SIZE);
|
||||||
state.deserialize(deser);
|
state.deserialize(deser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,6 @@ void serialize(Serializer& ser);
|
||||||
void deserialize(Deserializer& deser);
|
void deserialize(Deserializer& deser);
|
||||||
|
|
||||||
extern u8 *RAM;
|
extern u8 *RAM;
|
||||||
constexpr u32 ELAN_RAM_SIZE = 32 * 1024 * 1024;
|
extern u32 ERAM_SIZE;
|
||||||
constexpr u32 ELAN_RAM_MASK = ELAN_RAM_SIZE - 1;
|
constexpr u32 ERAM_SIZE_MAX = 32 * 1024 * 1024;
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,7 +235,6 @@ void bm_Reset()
|
||||||
{
|
{
|
||||||
// Windows cannot lock/unlock a region spanning more than one VirtualAlloc or MapViewOfFile
|
// Windows cannot lock/unlock a region spanning more than one VirtualAlloc or MapViewOfFile
|
||||||
// so we have to unlock each region individually
|
// so we have to unlock each region individually
|
||||||
// No need for this mess in 4GB mode since windows doesn't use it
|
|
||||||
if (settings.platform.ram_size == 16 * 1024 * 1024)
|
if (settings.platform.ram_size == 16 * 1024 * 1024)
|
||||||
{
|
{
|
||||||
mem_region_unlock(virt_ram_base + 0x0C000000, RAM_SIZE);
|
mem_region_unlock(virt_ram_base + 0x0C000000, RAM_SIZE);
|
||||||
|
@ -248,11 +247,6 @@ void bm_Reset()
|
||||||
mem_region_unlock(virt_ram_base + 0x0C000000, RAM_SIZE);
|
mem_region_unlock(virt_ram_base + 0x0C000000, RAM_SIZE);
|
||||||
mem_region_unlock(virt_ram_base + 0x0E000000, RAM_SIZE);
|
mem_region_unlock(virt_ram_base + 0x0E000000, RAM_SIZE);
|
||||||
}
|
}
|
||||||
if (_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
mem_region_unlock(virt_ram_base + 0x8C000000u, 0x90000000u - 0x8C000000u);
|
|
||||||
mem_region_unlock(virt_ram_base + 0xAC000000u, 0xB0000000u - 0xAC000000u);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -264,38 +258,18 @@ void bm_LockPage(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
addr = addr & (RAM_MASK - PAGE_MASK);
|
addr = addr & (RAM_MASK - PAGE_MASK);
|
||||||
if (_nvmem_enabled())
|
if (_nvmem_enabled())
|
||||||
{
|
|
||||||
mem_region_lock(virt_ram_base + 0x0C000000 + addr, size);
|
mem_region_lock(virt_ram_base + 0x0C000000 + addr, size);
|
||||||
if (_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
mem_region_lock(virt_ram_base + 0x8C000000 + addr, size);
|
|
||||||
mem_region_lock(virt_ram_base + 0xAC000000 + addr, size);
|
|
||||||
// TODO wraps
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
mem_region_lock(&mem_b[addr], size);
|
mem_region_lock(&mem_b[addr], size);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bm_UnlockPage(u32 addr, u32 size)
|
void bm_UnlockPage(u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
addr = addr & (RAM_MASK - PAGE_MASK);
|
addr = addr & (RAM_MASK - PAGE_MASK);
|
||||||
if (_nvmem_enabled())
|
if (_nvmem_enabled())
|
||||||
{
|
|
||||||
mem_region_unlock(virt_ram_base + 0x0C000000 + addr, size);
|
mem_region_unlock(virt_ram_base + 0x0C000000 + addr, size);
|
||||||
if (_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
mem_region_unlock(virt_ram_base + 0x8C000000 + addr, size);
|
|
||||||
mem_region_unlock(virt_ram_base + 0xAC000000 + addr, size);
|
|
||||||
// TODO wraps
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
mem_region_unlock(&mem_b[addr], size);
|
mem_region_unlock(&mem_b[addr], size);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bm_ResetCache()
|
void bm_ResetCache()
|
||||||
|
@ -618,18 +592,10 @@ u32 bm_getRamOffset(void *p)
|
||||||
{
|
{
|
||||||
if (_nvmem_enabled())
|
if (_nvmem_enabled())
|
||||||
{
|
{
|
||||||
if (_nvmem_4gb_space())
|
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x20000000)
|
||||||
{
|
return -1;
|
||||||
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x100000000L)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((u8 *)p < virt_ram_base || (u8 *)p >= virt_ram_base + 0x20000000)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
u32 addr = (u8*)p - virt_ram_base;
|
u32 addr = (u8*)p - virt_ram_base;
|
||||||
if (!IsOnRam(addr) || ((addr >> 29) > 0 && (addr >> 29) < 4)) // system RAM is not mapped to 20, 40 and 60 because of laziness
|
if (!IsOnRam(addr))
|
||||||
return -1;
|
return -1;
|
||||||
return addr & RAM_MASK;
|
return addr & RAM_MASK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,16 +385,7 @@ static void recSh4_Init()
|
||||||
|
|
||||||
|
|
||||||
if (_nvmem_enabled())
|
if (_nvmem_enabled())
|
||||||
{
|
verify(mem_b.data == ((u8*)p_sh4rcb->sq_buffer + 512 + 0x0C000000));
|
||||||
if (!_nvmem_4gb_space())
|
|
||||||
{
|
|
||||||
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x0C000000));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x8C000000));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare some pointer to the pre-allocated code cache:
|
// Prepare some pointer to the pre-allocated code cache:
|
||||||
void *candidate_ptr = (void*)(((unat)SH4_TCB + 4095) & ~4095);
|
void *candidate_ptr = (void*)(((unat)SH4_TCB + 4095) & ~4095);
|
||||||
|
|
|
@ -118,19 +118,19 @@ static mem_handle_t allocate_shared_filemem(unsigned size)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
||||||
// The function supports allocating 512MB or 4GB addr spaces.
|
|
||||||
// vmem_base_addr points to an address space of 512MB (or 4GB) that can be used for fast memory ops.
|
// vmem_base_addr points to an address space of 512MB that can be used for fast memory ops.
|
||||||
// In negative offsets of the pointer (up to FPCB size, usually 65/129MB) the context and jump table
|
// In negative offsets of the pointer (up to FPCB size, usually 65/129MB) the context and jump table
|
||||||
// can be found. If the platform init returns error, the user is responsible for initializing the
|
// can be found. If the platform init returns error, the user is responsible for initializing the
|
||||||
// memory using a fallback (that is, regular mallocs and falling back to slow memory JIT).
|
// memory using a fallback (that is, regular mallocs and falling back to slow memory JIT).
|
||||||
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
|
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
|
||||||
{
|
{
|
||||||
return MemTypeError;
|
return false;
|
||||||
#if 0
|
#if 0
|
||||||
const unsigned size_aligned = ((RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX + PAGE_SIZE) & (~(PAGE_SIZE-1)));
|
const unsigned size_aligned = ((RAM_SIZE_MAX + VRAM_SIZE_MAX + ARAM_SIZE_MAX + PAGE_SIZE) & (~(PAGE_SIZE-1)));
|
||||||
vmem_fd_page = allocate_shared_filemem(size_aligned);
|
vmem_fd_page = allocate_shared_filemem(size_aligned);
|
||||||
if (vmem_fd_page < 0)
|
if (vmem_fd_page < 0)
|
||||||
return MemTypeError;
|
return false;
|
||||||
|
|
||||||
vmem_fd_codememory = (uintptr_t)virtmemReserve(size_aligned);
|
vmem_fd_codememory = (uintptr_t)virtmemReserve(size_aligned);
|
||||||
|
|
||||||
|
@ -141,15 +141,12 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
|
||||||
WARN_LOG(VMEM, "Failed to set perms (platform_int)...");
|
WARN_LOG(VMEM, "Failed to set perms (platform_int)...");
|
||||||
|
|
||||||
// Now try to allocate a contiguous piece of memory.
|
// Now try to allocate a contiguous piece of memory.
|
||||||
VMemType rv;
|
|
||||||
if (reserved_base == NULL)
|
if (reserved_base == NULL)
|
||||||
{
|
{
|
||||||
reserved_size = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
|
reserved_size = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
|
||||||
reserved_base = mem_region_reserve(NULL, reserved_size);
|
reserved_base = mem_region_reserve(NULL, reserved_size);
|
||||||
if (!reserved_base)
|
if (!reserved_base)
|
||||||
return MemTypeError;
|
return false;
|
||||||
|
|
||||||
rv = MemType512MB;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*sh4rcb_addr = reserved_base;
|
*sh4rcb_addr = reserved_base;
|
||||||
|
@ -160,7 +157,7 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
|
||||||
// Now map the memory for the SH4 context, do not include FPCB on purpose (paged on demand).
|
// Now map the memory for the SH4 context, do not include FPCB on purpose (paged on demand).
|
||||||
mem_region_unlock(sh4rcb_base_ptr, sizeof(Sh4RCB) - fpcb_size);
|
mem_region_unlock(sh4rcb_base_ptr, sizeof(Sh4RCB) - fpcb_size);
|
||||||
|
|
||||||
return rv;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,39 +148,28 @@ static int allocate_shared_filemem(unsigned size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
||||||
// The function supports allocating 512MB or 4GB addr spaces.
|
|
||||||
|
|
||||||
int vmem_fd = -1;
|
int vmem_fd = -1;
|
||||||
static int shmem_fd2 = -1;
|
static int shmem_fd2 = -1;
|
||||||
static void *reserved_base;
|
static void *reserved_base;
|
||||||
static size_t reserved_size;
|
static size_t reserved_size;
|
||||||
|
|
||||||
// vmem_base_addr points to an address space of 512MB (or 4GB) that can be used for fast memory ops.
|
// vmem_base_addr points to an address space of 512MB that can be used for fast memory ops.
|
||||||
// In negative offsets of the pointer (up to FPCB size, usually 65/129MB) the context and jump table
|
// In negative offsets of the pointer (up to FPCB size, usually 65/129MB) the context and jump table
|
||||||
// can be found. If the platform init returns error, the user is responsible for initializing the
|
// can be found. If the platform init returns error, the user is responsible for initializing the
|
||||||
// memory using a fallback (that is, regular mallocs and falling back to slow memory JIT).
|
// memory using a fallback (that is, regular mallocs and falling back to slow memory JIT).
|
||||||
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize) {
|
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize) {
|
||||||
// Firt let's try to allocate the shm-backed memory
|
// Firt let's try to allocate the shm-backed memory
|
||||||
vmem_fd = allocate_shared_filemem(ramSize);
|
vmem_fd = allocate_shared_filemem(ramSize);
|
||||||
if (vmem_fd < 0)
|
if (vmem_fd < 0)
|
||||||
return MemTypeError;
|
return false;
|
||||||
|
|
||||||
// Now try to allocate a contiguous piece of memory.
|
// Now try to allocate a contiguous piece of memory.
|
||||||
VMemType rv;
|
reserved_size = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
|
||||||
#if HOST_CPU == CPU_X64 || HOST_CPU == CPU_ARM64
|
|
||||||
reserved_size = 0x100000000L + sizeof(Sh4RCB) + 0x10000; // 4GB + context size + 64K padding
|
|
||||||
reserved_base = mem_region_reserve(NULL, reserved_size);
|
reserved_base = mem_region_reserve(NULL, reserved_size);
|
||||||
rv = MemType4GB;
|
if (!reserved_base) {
|
||||||
#endif
|
close(vmem_fd);
|
||||||
if (reserved_base == NULL)
|
return false;
|
||||||
{
|
|
||||||
reserved_size = 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE_MAX + 0x10000;
|
|
||||||
reserved_base = mem_region_reserve(NULL, reserved_size);
|
|
||||||
if (!reserved_base) {
|
|
||||||
close(vmem_fd);
|
|
||||||
return MemTypeError;
|
|
||||||
}
|
|
||||||
rv = MemType512MB;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align pointer to 64KB too, some Linaro bug (no idea but let's just be safe I guess).
|
// Align pointer to 64KB too, some Linaro bug (no idea but let's just be safe I guess).
|
||||||
|
@ -194,7 +183,7 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
|
||||||
// Now map the memory for the SH4 context, do not include FPCB on purpose (paged on demand).
|
// Now map the memory for the SH4 context, do not include FPCB on purpose (paged on demand).
|
||||||
mem_region_unlock(sh4rcb_base_ptr, sizeof(Sh4RCB) - fpcb_size);
|
mem_region_unlock(sh4rcb_base_ptr, sizeof(Sh4RCB) - fpcb_size);
|
||||||
|
|
||||||
return rv;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just tries to wipe as much as possible in the relevant area.
|
// Just tries to wipe as much as possible in the relevant area.
|
||||||
|
|
|
@ -1825,17 +1825,10 @@ private:
|
||||||
|
|
||||||
Instruction *start_instruction = GetCursorAddress<Instruction *>();
|
Instruction *start_instruction = GetCursorAddress<Instruction *>();
|
||||||
|
|
||||||
// WARNING: the rewrite code relies on having 1 or 2 ops before the memory access
|
// WARNING: the rewrite code relies on having 2 ops before the memory access
|
||||||
// Update ngen_Rewrite (and perhaps read_memory_rewrite_size) if adding or removing code
|
// Update ngen_Rewrite (and perhaps read_memory_rewrite_size) if adding or removing code
|
||||||
if (!_nvmem_4gb_space())
|
Ubfx(x1, x0, 0, 29);
|
||||||
{
|
Add(x1, x1, sizeof(Sh4Context), LeaveFlags);
|
||||||
Ubfx(x1, x0, 0, 29);
|
|
||||||
Add(x1, x1, sizeof(Sh4Context), LeaveFlags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Add(x1, x0, sizeof(Sh4Context), LeaveFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 size = op.flags & 0x7f;
|
u32 size = op.flags & 0x7f;
|
||||||
switch(size)
|
switch(size)
|
||||||
|
@ -1998,17 +1991,10 @@ private:
|
||||||
|
|
||||||
Instruction *start_instruction = GetCursorAddress<Instruction *>();
|
Instruction *start_instruction = GetCursorAddress<Instruction *>();
|
||||||
|
|
||||||
// WARNING: the rewrite code relies on having 1 or 2 ops before the memory access
|
// WARNING: the rewrite code relies on having 2 ops before the memory access
|
||||||
// Update ngen_Rewrite (and perhaps write_memory_rewrite_size) if adding or removing code
|
// Update ngen_Rewrite (and perhaps write_memory_rewrite_size) if adding or removing code
|
||||||
if (!_nvmem_4gb_space())
|
Ubfx(x7, x0, 0, 29);
|
||||||
{
|
Add(x7, x7, sizeof(Sh4Context), LeaveFlags);
|
||||||
Ubfx(x7, x0, 0, 29);
|
|
||||||
Add(x7, x7, sizeof(Sh4Context), LeaveFlags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Add(x7, x0, sizeof(Sh4Context), LeaveFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 size = op.flags & 0x7f;
|
u32 size = op.flags & 0x7f;
|
||||||
switch(size)
|
switch(size)
|
||||||
|
@ -2279,7 +2265,7 @@ bool ngen_Rewrite(host_context_t &context, void *faultAddress)
|
||||||
verify(found);
|
verify(found);
|
||||||
|
|
||||||
// Skip the preceding ops (add, ubfx)
|
// Skip the preceding ops (add, ubfx)
|
||||||
u32 *code_rewrite = code_ptr - 1 - (!_nvmem_4gb_space() ? 1 : 0);
|
u32 *code_rewrite = code_ptr - 2;
|
||||||
Arm64Assembler *assembler = new Arm64Assembler(code_rewrite);
|
Arm64Assembler *assembler = new Arm64Assembler(code_rewrite);
|
||||||
if (is_read)
|
if (is_read)
|
||||||
assembler->GenReadMemorySlow(size);
|
assembler->GenReadMemorySlow(size);
|
||||||
|
|
|
@ -741,13 +741,7 @@ public:
|
||||||
|
|
||||||
//found !
|
//found !
|
||||||
const u8 *start = getCurr();
|
const u8 *start = getCurr();
|
||||||
u32 memAddress = _nvmem_4gb_space() ?
|
u32 memAddress = context.r9;
|
||||||
#ifdef _WIN32
|
|
||||||
context.rcx
|
|
||||||
#else
|
|
||||||
context.rdi
|
|
||||||
#endif
|
|
||||||
: context.r9;
|
|
||||||
if (op == MemOp::W && size >= MemSize::S32 && (memAddress >> 26) == 0x38)
|
if (op == MemOp::W && size >= MemSize::S32 && (memAddress >> 26) == 0x38)
|
||||||
call(MemHandlers[MemType::StoreQueue][size][MemOp::W]);
|
call(MemHandlers[MemType::StoreQueue][size][MemOp::W]);
|
||||||
else
|
else
|
||||||
|
@ -759,12 +753,11 @@ public:
|
||||||
context.pc = (uintptr_t)(retAddr - 5);
|
context.pc = (uintptr_t)(retAddr - 5);
|
||||||
// remove the call from the stack
|
// remove the call from the stack
|
||||||
context.rsp += 8;
|
context.rsp += 8;
|
||||||
if (!_nvmem_4gb_space())
|
//restore the addr from r9 to arg0 (rcx or rdi) so it's valid again
|
||||||
//restore the addr from r9 to arg0 (rcx or rdi) so it's valid again
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
context.rcx = memAddress;
|
context.rcx = memAddress;
|
||||||
#else
|
#else
|
||||||
context.rdi = memAddress;
|
context.rdi = memAddress;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -781,6 +774,7 @@ private:
|
||||||
{
|
{
|
||||||
if (mmu_enabled())
|
if (mmu_enabled())
|
||||||
{
|
{
|
||||||
|
#ifdef FAST_MMU
|
||||||
Xbyak::Label inCache;
|
Xbyak::Label inCache;
|
||||||
Xbyak::Label done;
|
Xbyak::Label done;
|
||||||
|
|
||||||
|
@ -797,15 +791,18 @@ private:
|
||||||
}
|
}
|
||||||
test(eax, eax);
|
test(eax, eax);
|
||||||
jne(inCache);
|
jne(inCache);
|
||||||
|
#endif
|
||||||
mov(call_regs[1], write);
|
mov(call_regs[1], write);
|
||||||
mov(call_regs[2], block->vaddr + op.guest_offs - (op.delay_slot ? 2 : 0)); // pc
|
mov(call_regs[2], block->vaddr + op.guest_offs - (op.delay_slot ? 2 : 0)); // pc
|
||||||
GenCall(mmuDynarecLookup);
|
GenCall(mmuDynarecLookup);
|
||||||
mov(call_regs[0], eax);
|
mov(call_regs[0], eax);
|
||||||
|
#ifdef FAST_MMU
|
||||||
jmp(done);
|
jmp(done);
|
||||||
L(inCache);
|
L(inCache);
|
||||||
and_(call_regs[0], 0xFFF);
|
and_(call_regs[0], 0xFFF);
|
||||||
or_(call_regs[0], eax);
|
or_(call_regs[0], eax);
|
||||||
L(done);
|
L(done);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool GenReadMemImmediate(const shil_opcode& op, RuntimeBlockInfo* block)
|
bool GenReadMemImmediate(const shil_opcode& op, RuntimeBlockInfo* block)
|
||||||
|
@ -1125,11 +1122,9 @@ private:
|
||||||
if (type == MemType::Fast && _nvmem_enabled())
|
if (type == MemType::Fast && _nvmem_enabled())
|
||||||
{
|
{
|
||||||
mov(rax, (uintptr_t)virt_ram_base);
|
mov(rax, (uintptr_t)virt_ram_base);
|
||||||
if (!_nvmem_4gb_space())
|
mov(r9, call_regs64[0]);
|
||||||
{
|
and_(call_regs[0], 0x1FFFFFFF);
|
||||||
mov(r9, call_regs64[0]);
|
|
||||||
and_(call_regs[0], 0x1FFFFFFF);
|
|
||||||
}
|
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
case MemSize::S8:
|
case MemSize::S8:
|
||||||
|
|
|
@ -45,14 +45,13 @@ static std::vector<void *> unmapped_regions;
|
||||||
static std::vector<void *> mapped_regions;
|
static std::vector<void *> mapped_regions;
|
||||||
|
|
||||||
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
// Implement vmem initialization for RAM, ARAM, VRAM and SH4 context, fpcb etc.
|
||||||
// The function supports allocating 512MB or 4GB addr spaces.
|
|
||||||
|
|
||||||
// Please read the POSIX implementation for more information. On Windows this is
|
// Please read the POSIX implementation for more information. On Windows this is
|
||||||
// rather straightforward.
|
// rather straightforward.
|
||||||
VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
|
bool vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ramSize)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_UWP
|
#ifdef TARGET_UWP
|
||||||
return MemTypeError;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
unmapped_regions.reserve(32);
|
unmapped_regions.reserve(32);
|
||||||
mapped_regions.reserve(32);
|
mapped_regions.reserve(32);
|
||||||
|
@ -81,7 +80,7 @@ VMemType vmem_platform_init(void **vmem_base_addr, void **sh4rcb_addr, size_t ra
|
||||||
verify(ptr == *vmem_base_addr);
|
verify(ptr == *vmem_base_addr);
|
||||||
unmapped_regions.push_back(ptr);
|
unmapped_regions.push_back(ptr);
|
||||||
|
|
||||||
return MemType512MB;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just tries to wipe as much as possible in the relevant area.
|
// Just tries to wipe as much as possible in the relevant area.
|
||||||
|
|
Loading…
Reference in New Issue