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:
Flyinghead 2022-12-09 17:37:49 +01:00
parent 9069a49145
commit 32e3e7d9c5
13 changed files with 99 additions and 404 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;
} }
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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);

View File

@ -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
} }

View File

@ -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.

View File

@ -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);

View File

@ -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:

View File

@ -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.