redquark-amiberry-rb/src/osdep/amiberry_mem.cpp
2017-09-19 14:24:41 +02:00

502 lines
No EOL
13 KiB
C++

#include "sysconfig.h"
#include "sysdeps.h"
#include "config.h"
#include "uae.h"
#include "options.h"
#include "gui.h"
#include "include/memory.h"
#include "newcpu.h"
#include "custom.h"
#include "autoconf.h"
#include "akiko.h"
#include "ar.h"
#include "uae/mman.h"
#include <sys/mman.h>
#include <SDL.h>
uae_u8* natmem_offset = nullptr;
uae_u32 natmem_size;
uae_u32 max_z3fastmem;
/* JIT can access few bytes outside of memory block of it executes code at the very end of memory block */
#define BARRIER 32
static uae_u8* additional_mem = (uae_u8*)MAP_FAILED;
#define ADDITIONAL_MEMSIZE (128 + 16) * 1024 * 1024
static uae_u8* a3000_mem = (uae_u8*)MAP_FAILED;
static int a3000_totalsize = 0;
#define A3000MEM_START 0x08000000
static int lastLowSize = 0;
static int lastHighSize = 0;
int z3base_adr = 0;
void free_AmigaMem(void)
{
if (natmem_offset != 0)
{
free(natmem_offset);
natmem_offset = 0;
}
if (additional_mem != MAP_FAILED)
{
munmap(additional_mem, ADDITIONAL_MEMSIZE + BARRIER);
additional_mem = (uae_u8*)MAP_FAILED;
}
if (a3000_mem != MAP_FAILED)
{
munmap(a3000_mem, a3000_totalsize);
a3000_mem = (uae_u8*)MAP_FAILED;
a3000_totalsize = 0;
}
}
void alloc_AmigaMem(void)
{
int i;
uae_u64 total;
int max_allowed_mman;
free_AmigaMem();
set_expamem_z3_hack_mode(Z3MAPPING_AUTO);
// First attempt: allocate 16 MB for all memory in 24-bit area
// and additional mem for Z3 and RTG at correct offset
natmem_size = 16 * 1024 * 1024;
natmem_offset = (uae_u8*)valloc(natmem_size + BARRIER);
max_z3fastmem = ADDITIONAL_MEMSIZE - (16 * 1024 * 1024);
if (!natmem_offset) {
write_log("Can't allocate 16M of virtual address space!?\n");
abort();
}
additional_mem = (uae_u8*)mmap(natmem_offset + Z3BASE_REAL, ADDITIONAL_MEMSIZE + BARRIER,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (additional_mem != MAP_FAILED)
{
// Allocation successful -> we can use natmem_offset for entire memory access at real address
changed_prefs.z3autoconfig_start = currprefs.z3autoconfig_start = Z3BASE_REAL;
z3base_adr = Z3BASE_REAL;
write_log("Allocated 16 MB for 24-bit area (0x%08x) and %d MB for Z3 and RTG at real address (0x%08x - 0x%08x)\n",
natmem_offset, ADDITIONAL_MEMSIZE / (1024 * 1024), additional_mem, additional_mem + ADDITIONAL_MEMSIZE + BARRIER);
set_expamem_z3_hack_mode(Z3MAPPING_REAL);
return;
}
additional_mem = (uae_u8*)mmap(natmem_offset + Z3BASE_UAE, ADDITIONAL_MEMSIZE + BARRIER,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (additional_mem != MAP_FAILED)
{
// Allocation successful -> we can use natmem_offset for entire memory access at fake address
changed_prefs.z3autoconfig_start = currprefs.z3autoconfig_start = Z3BASE_UAE;
z3base_adr = Z3BASE_UAE;
write_log("Allocated 16 MB for 24-bit area (0x%08x) and %d MB for Z3 and RTG at fake address (0x%08x - 0x%08x)\n",
natmem_offset, ADDITIONAL_MEMSIZE / (1024 * 1024), additional_mem, additional_mem + ADDITIONAL_MEMSIZE + BARRIER);
set_expamem_z3_hack_mode(Z3MAPPING_UAE);
return;
}
free(natmem_offset);
// Next attempt: allocate huge memory block for entire area
natmem_size = ADDITIONAL_MEMSIZE + 256 * 1024 * 1024;
natmem_offset = (uae_u8*)valloc(natmem_size + BARRIER);
if (natmem_offset)
{
// Allocation successful
changed_prefs.z3autoconfig_start = currprefs.z3autoconfig_start = Z3BASE_UAE;
z3base_adr = Z3BASE_UAE;
write_log("Allocated %d MB for entire memory\n", natmem_size / (1024 * 1024));
return;
}
// No mem for Z3 or RTG at all
natmem_size = 16 * 1024 * 1024;
natmem_offset = (uae_u8*)valloc(natmem_size + BARRIER);
if (!natmem_offset) {
write_log("Can't allocate 16M of virtual address space!?\n");
abort();
}
changed_prefs.z3autoconfig_start = currprefs.z3autoconfig_start = 0x00000000; // No mem for Z3
z3base_adr = 0x00000000;
max_z3fastmem = 0;
write_log("Reserved: %p-%p (0x%08x %dM)\n", natmem_offset, (uae_u8*)natmem_offset + natmem_size,
natmem_size, natmem_size >> 20);
}
static bool HandleA3000Mem(int lowsize, int highsize)
{
bool result = true;
if (lowsize == lastLowSize && highsize == lastHighSize)
return result;
if (a3000_mem != MAP_FAILED)
{
write_log("HandleA3000Mem(): Free A3000 memory (0x%08x). %d MB.\n", a3000_mem, a3000_totalsize / (1024 * 1024));
munmap(a3000_mem, a3000_totalsize);
a3000_mem = (uae_u8*)MAP_FAILED;
a3000_totalsize = 0;
lastLowSize = 0;
lastHighSize = 0;
}
if (lowsize + highsize > 0)
{
// Try to get memory for A3000 motherboard
write_log("Try to get A3000 memory at correct place (0x%08x). %d MB and %d MB.\n", A3000MEM_START,
lowsize / (1024 * 1024), highsize / (1024 * 1024));
a3000_totalsize = lowsize + highsize;
a3000_mem = (uae_u8*)mmap(natmem_offset + (A3000MEM_START - lowsize), a3000_totalsize,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (a3000_mem != MAP_FAILED)
{
lastLowSize = lowsize;
lastHighSize = highsize;
write_log(_T("Succeeded: location at 0x%08x (Amiga: 0x%08x)\n"), a3000_mem, (A3000MEM_START - lowsize));
}
else
{
write_log("Failed.\n");
a3000_totalsize = 0;
result = false;
}
}
return result;
}
static bool A3000MemAvailable(void)
{
return (a3000_mem != MAP_FAILED);
}
bool uae_mman_info(addrbank *ab, struct uae_mman_data *md)
{
bool got = false;
bool readonly = false;
uaecptr start;
uae_u32 size = ab->reserved_size;
uae_u32 readonlysize = size;
bool barrier = false;
if (!_tcscmp(ab->label, _T("*"))) {
start = ab->start;
got = true;
if (expansion_get_autoconfig_by_address(&currprefs, ab->start) && !expansion_get_autoconfig_by_address(&currprefs, ab->start + size))
barrier = true;
}
else if (!_tcscmp(ab->label, _T("*B"))) {
start = ab->start;
got = true;
barrier = true;
}
else if (!_tcscmp(ab->label, _T("chip"))) {
start = 0;
got = true;
if (!expansion_get_autoconfig_by_address(&currprefs, 0x00200000) && currprefs.chipmem_size == 2 * 1024 * 1024)
barrier = true;
if (currprefs.chipmem_size > 2 * 1024 * 1024)
barrier = true;
}
else if (!_tcscmp(ab->label, _T("kick"))) {
start = 0xf80000;
got = true;
barrier = true;
readonly = true;
}
else if (!_tcscmp(ab->label, _T("rom_a8"))) {
start = 0xa80000;
got = true;
readonly = true;
}
else if (!_tcscmp(ab->label, _T("rom_e0"))) {
start = 0xe00000;
got = true;
readonly = true;
}
else if (!_tcscmp(ab->label, _T("rom_f0"))) {
start = 0xf00000;
got = true;
readonly = true;
}
else if (!_tcscmp(ab->label, _T("rom_f0_ppc"))) {
// this is flash and also contains IO
start = 0xf00000;
got = true;
readonly = false;
}
else if (!_tcscmp(ab->label, _T("rtarea"))) {
start = rtarea_base;
got = true;
readonly = true;
readonlysize = RTAREA_TRAPS;
}
else if (!_tcscmp(ab->label, _T("ramsey_low"))) {
if (ab->reserved_size != lastLowSize)
HandleA3000Mem(ab->reserved_size, lastHighSize);
if (A3000MemAvailable()) {
start = a3000lmem_bank.start;
got = true;
}
}
else if (!_tcscmp(ab->label, _T("csmk1_maprom"))) {
start = 0x07f80000;
got = true;
}
else if (!_tcscmp(ab->label, _T("25bitram"))) {
start = 0x01000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("ramsey_high"))) {
if (ab->reserved_size != lastHighSize)
HandleA3000Mem(lastLowSize, ab->reserved_size);
if (A3000MemAvailable()) {
start = 0x08000000;
got = true;
}
}
else if (!_tcscmp(ab->label, _T("dkb"))) {
start = 0x10000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("fusionforty"))) {
start = 0x11000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("blizzard_40"))) {
start = 0x40000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("blizzard_48"))) {
start = 0x48000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("blizzard_68"))) {
start = 0x68000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("blizzard_70"))) {
start = 0x70000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("cyberstorm"))) {
start = 0x0c000000;
got = true;
}
else if (!_tcscmp(ab->label, _T("cyberstormmaprom"))) {
start = 0xfff00000;
got = true;
}
else if (!_tcscmp(ab->label, _T("bogo"))) {
start = 0x00C00000;
got = true;
if (currprefs.bogomem_size <= 0x100000)
barrier = true;
}
else if (!_tcscmp(ab->label, _T("custmem1"))) {
start = currprefs.custom_memory_addrs[0];
got = true;
}
else if (!_tcscmp(ab->label, _T("custmem2"))) {
start = currprefs.custom_memory_addrs[1];
got = true;
}
else if (!_tcscmp(ab->label, _T("hrtmem"))) {
start = 0x00a10000;
got = true;
}
else if (!_tcscmp(ab->label, _T("arhrtmon"))) {
start = 0x00800000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("xpower_e2"))) {
start = 0x00e20000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("xpower_f2"))) {
start = 0x00f20000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("nordic_f0"))) {
start = 0x00f00000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("nordic_f4"))) {
start = 0x00f40000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("nordic_f6"))) {
start = 0x00f60000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("superiv_b0"))) {
start = 0x00b00000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("superiv_d0"))) {
start = 0x00d00000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("superiv_e0"))) {
start = 0x00e00000;
barrier = true;
got = true;
}
else if (!_tcscmp(ab->label, _T("ram_a8"))) {
start = 0x00a80000;
barrier = true;
got = true;
}
if (got) {
md->start = start;
md->size = size;
md->readonly = readonly;
md->readonlysize = readonlysize;
md->hasbarrier = barrier;
if (md->hasbarrier) {
md->size += BARRIER;
}
}
return got;
}
bool mapped_malloc(addrbank *ab)
{
if (ab->allocated_size) {
write_log(_T("mapped_malloc with memory bank '%s' already allocated!?\n"), ab->name);
}
ab->allocated_size = 0;
if (ab->label && ab->label[0] == '*') {
if (ab->start == 0 || ab->start == 0xffffffff) {
write_log(_T("mapped_malloc(*) without start address!\n"));
return false;
}
}
struct uae_mman_data md = { 0 };
uaecptr start = ab->start;
if (uae_mman_info(ab, &md)) {
start = md.start;
ab->baseaddr = natmem_offset + start;
}
if (ab->baseaddr) {
if (md.hasbarrier) {
// fill end of ram with ILLEGAL to catch direct PC falling out of RAM.
put_long_host(ab->baseaddr + ab->reserved_size, 0x4afc4afc);
}
ab->allocated_size = ab->reserved_size;
write_log("mapped_malloc(): 0x%08x - 0x%08x (0x%08x - 0x%08x) -> %s (%s)\n",
ab->baseaddr - natmem_offset, ab->baseaddr - natmem_offset + ab->allocated_size,
ab->baseaddr, ab->baseaddr + ab->allocated_size, ab->name, ab->label);
}
ab->flags |= ABFLAG_DIRECTMAP;
return (ab->baseaddr != NULL);
}
void mapped_free(addrbank *ab)
{
if (ab->label != NULL && !strcmp(ab->label, "filesys") && ab->baseaddr != NULL) {
free(ab->baseaddr);
write_log("mapped_free(): 0x%08x - 0x%08x (0x%08x - 0x%08x) -> %s (%s)\n",
ab->baseaddr - natmem_offset, ab->baseaddr - natmem_offset + ab->allocated_size,
ab->baseaddr, ab->baseaddr + ab->allocated_size, ab->name, ab->label);
}
ab->baseaddr = NULL;
ab->allocated_size = 0;
}
void protect_roms(bool protect)
{
/*
If this code is enabled, we can't switch back from JIT to nonJIT emulation...
if (protect) {
// protect only if JIT enabled, always allow unprotect
if (!currprefs.cachesize)
return;
}
// Protect all regions, which contains ROM
if(extendedkickmem_bank.baseaddr != NULL)
mprotect(extendedkickmem_bank.baseaddr, 0x80000, protect ? PROT_READ : PROT_READ | PROT_WRITE);
if(extendedkickmem2_bank.baseaddr != NULL)
mprotect(extendedkickmem2_bank.baseaddr, 0x80000, protect ? PROT_READ : PROT_READ | PROT_WRITE);
if(kickmem_bank.baseaddr != NULL)
mprotect(kickmem_bank.baseaddr, 0x80000, protect ? PROT_READ : PROT_READ | PROT_WRITE);
if(rtarea != NULL)
mprotect(rtarea, RTAREA_SIZE, protect ? PROT_READ : PROT_READ | PROT_WRITE);
if(filesysory != NULL)
mprotect(filesysory, 0x10000, protect ? PROT_READ : PROT_READ | PROT_WRITE);
*/
}
static int doinit_shm(void)
{
expansion_scan_autoconfig(&currprefs, true);
return 1;
}
static uae_u32 oz3fastmem_size[MAX_RAM_BOARDS];
static uae_u32 ofastmem_size[MAX_RAM_BOARDS];
static uae_u32 ortgmem_size[MAX_RTG_BOARDS];
static int ortgmem_type[MAX_RTG_BOARDS];
bool init_shm(void)
{
bool changed = false;
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
if (oz3fastmem_size[i] != changed_prefs.z3fastmem[i].size)
changed = true;
if (ofastmem_size[i] != changed_prefs.fastmem[i].size)
changed = true;
}
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
if (ortgmem_size[i] != changed_prefs.rtgboards[i].rtgmem_size)
changed = true;
if (ortgmem_type[i] != changed_prefs.rtgboards[i].rtgmem_type)
changed = true;
}
if (!changed)
return true;
for (int i = 0; i < MAX_RAM_BOARDS; i++) {
oz3fastmem_size[i] = changed_prefs.z3fastmem[i].size;
ofastmem_size[i] = changed_prefs.fastmem[i].size;
}
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
ortgmem_size[i] = changed_prefs.rtgboards[i].rtgmem_size;
ortgmem_type[i] = changed_prefs.rtgboards[i].rtgmem_type;
}
if (doinit_shm() < 0)
return false;
memory_hardreset(2);
return true;
}