Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Libretro
flycast
Commits
4c909bac
Commit
4c909bac
authored
May 31, 2019
by
Flyinghead
Browse files
Unify vmem/vmem32 (WIP). Support different RX and RW ptrs
parent
2230e913
Changes
18
Hide whitespace changes
Inline
Side-by-side
Makefile.common
View file @
4c909bac
...
...
@@ -311,7 +311,8 @@ endif
SOURCES_CXX
+=
$(CORE_DIR)
/core/libretro/libretro.cpp
\
$(CORE_DIR)
/core/libretro/audiostream.cpp
\
$(CORE_DIR)
/core/libretro/common.cpp
$(CORE_DIR)
/core/libretro/common.cpp
\
$(CORE_DIR)
/core/libretro/vmem_utils.cpp
SOURCES_C
+=
$(LIBRETRO_COMM_DIR)
/memmap/memalign.c
\
$(LIBRETRO_COMM_DIR)
/file/retro_stat.c
...
...
core/build.h
View file @
4c909bac
...
...
@@ -251,3 +251,15 @@
#ifdef HOST_NO_AREC
#error Dont use HOST_NO_AREC
#endif
// Some restrictions on FEAT_NO_RWX_PAGES
#if defined(FEAT_NO_RWX_PAGES) && FEAT_SHREC == DYNAREC_JIT
#if HOST_CPU != CPU_X64 && HOST_CPU != CPU_ARM64
#error "FEAT_NO_RWX_PAGES Only implemented for X64 and ARMv8"
#endif
#endif
#define RAM_SIZE_MAX (32*1024*1024)
#define VRAM_SIZE_MAX (16*1024*1024)
#define ARAM_SIZE_MAX (8*1024*1024)
core/hw/aica/dsp_arm64.cpp
View file @
4c909bac
...
...
@@ -27,7 +27,7 @@
#include "deps/vixl/aarch64/macro-assembler-aarch64.h"
using
namespace
vixl
::
aarch64
;
extern
void
Arm64CacheFlush
(
void
*
start
,
void
*
end
);
extern
void
vmem_platform_flush_cache
(
void
*
icache_start
,
void
*
icache_end
,
void
*
dcache_start
,
void
*
dcache_
end
);
class
DSPAssembler
:
public
MacroAssembler
{
...
...
@@ -53,10 +53,9 @@ public:
Stp
(
xzr
,
xzr
,
MemOperand
(
x0
,
48
));
Ret
();
FinalizeCode
();
#ifdef _ANDROID
Arm64CacheFlush
(
GetBuffer
()
->
GetStartAddress
<
void
*>
(),
GetBuffer
()
->
GetEndAddress
<
void
*>
());
#endif
vmem_platform_flush_cache
(
GetBuffer
()
->
GetStartAddress
<
void
*>
(),
GetBuffer
()
->
GetEndAddress
<
void
*>
(),
GetBuffer
()
->
GetStartAddress
<
void
*>
(),
GetBuffer
()
->
GetEndAddress
<
void
*>
());
return
;
}
...
...
@@ -367,7 +366,9 @@ public:
FinalizeCode
();
Arm64CacheFlush
(
GetBuffer
()
->
GetStartAddress
<
void
*>
(),
GetBuffer
()
->
GetEndAddress
<
void
*>
());
vmem_platform_flush_cache
(
GetBuffer
()
->
GetStartAddress
<
void
*>
(),
GetBuffer
()
->
GetEndAddress
<
void
*>
(),
GetBuffer
()
->
GetStartAddress
<
void
*>
(),
GetBuffer
()
->
GetEndAddress
<
void
*>
());
}
private:
...
...
core/hw/arm7/arm64.cpp
View file @
4c909bac
...
...
@@ -28,7 +28,7 @@
using
namespace
vixl
::
aarch64
;
//#include "deps/vixl/aarch32/disasm-aarch32.h"
extern
void
Arm64CacheFlush
(
void
*
start
,
void
*
end
);
extern
void
vmem_platform_flush_cache
(
void
*
icache_start
,
void
*
icache_end
,
void
*
dcache_start
,
void
*
dcache_
end
);
extern
u32
arm_single_op
(
u32
opcode
);
extern
"C"
void
arm_dispatch
();
extern
"C"
void
arm_exit
();
...
...
@@ -41,7 +41,7 @@ extern reg_pair arm_Reg[RN_ARM_REG_COUNT];
MacroAssembler
*
assembler
;
extern
"C"
void
armFlushICache
(
void
*
bgn
,
void
*
end
)
{
Arm64CacheFlush
(
bgn
,
end
);
vmem_platform_flush_cache
(
bgn
,
end
,
bgn
,
end
);
}
static
MemOperand
arm_reg_operand
(
u32
regn
)
...
...
@@ -143,7 +143,9 @@ void armv_end(void* codestart, u32 cycl)
assembler
->
FinalizeCode
();
verify
(
assembler
->
GetBuffer
()
->
GetCursorOffset
()
<=
assembler
->
GetBuffer
()
->
GetCapacity
());
Arm64CacheFlush
(
codestart
,
assembler
->
GetBuffer
()
->
GetEndAddress
<
void
*>
());
vmem_platform_flush_cache
(
codestart
,
assembler
->
GetBuffer
()
->
GetEndAddress
<
void
*>
(),
codestart
,
assembler
->
GetBuffer
()
->
GetEndAddress
<
void
*>
());
icPtr
+=
assembler
->
GetBuffer
()
->
GetSizeInBytes
();
#if 0
...
...
core/hw/mem/_vmem.cpp
View file @
4c909bac
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#endif
#include <set>
#include "_vmem.h"
#include "vmem32.h"
#include "hw/aica/aica_if.h"
#include "hw/sh4/dyna/blockmanager.h"
...
...
@@ -33,7 +22,6 @@ _vmem_WriteMem32FP* _vmem_WF32[HANDLER_COUNT];
//upper 8b of the address
void
*
_vmem_MemInfo_ptr
[
0x100
];
void
_vmem_get_ptrs
(
u32
sz
,
bool
write
,
void
***
vmap
,
void
***
func
)
{
*
vmap
=
_vmem_MemInfo_ptr
;
...
...
@@ -429,6 +417,7 @@ void _vmem_term()
#include "hw/sh4/sh4_mem.h"
u8
*
virt_ram_base
;
bool
vmem_4gb_space
;
void
*
malloc_pages
(
size_t
size
)
{
#ifdef _WIN32
...
...
@@ -444,380 +433,206 @@ void* malloc_pages(size_t size) {
#endif
}
static
bool
_vmem_reserve_nonvmem
(
void
)
{
virt_ram_base
=
0
;
p_sh4rcb
=
(
Sh4RCB
*
)
malloc_pages
(
sizeof
(
Sh4RCB
));
mem_b
.
size
=
RAM_SIZE
;
mem_b
.
data
=
(
u8
*
)
malloc_pages
(
RAM_SIZE
);
vram
.
size
=
VRAM_SIZE
;
vram
.
data
=
(
u8
*
)
malloc_pages
(
VRAM_SIZE
);
aica_ram
.
size
=
ARAM_SIZE
;
aica_ram
.
data
=
(
u8
*
)
malloc_pages
(
ARAM_SIZE
);
return
true
;
}
void
_vmem_bm_reset_nvmem
(
void
);
// Resets the FPCB table (by either clearing it to the default val
// or by flushing it and making it fault on access again.
void
_vmem_bm_reset
(
void
)
{
#if !defined(TARGET_NO_NVMEM)
if
(
virt_ram_base
)
{
_vmem_bm_reset_nvmem
();
}
#endif
#if FEAT_SHREC != DYNAREC_NONE
if
(
!
virt_ram_base
)
bm_vmem_pagefill
((
void
**
)
p_sh4rcb
->
fpcb
,
FPCB_SIZE
);
#endif
// If we allocated it via vmem:
if
(
virt_ram_base
)
vmem_platform_reset_mem
(
p_sh4rcb
->
fpcb
,
sizeof
(
p_sh4rcb
->
fpcb
));
else
// We allocated it via a regular malloc/new/whatever on the heap
bm_vmem_pagefill
((
void
**
)
p_sh4rcb
->
fpcb
,
sizeof
(
p_sh4rcb
->
fpcb
));
}
#if !defined(TARGET_NO_NVMEM)
#define MAP_RAM_START_OFFSET 0
#define MAP_VRAM_START_OFFSET (MAP_RAM_START_OFFSET+RAM_SIZE)
#define MAP_ARAM_START_OFFSET (MAP_VRAM_START_OFFSET+VRAM_SIZE)
#ifdef _WIN32
HANDLE
mem_handle
;
static
void
*
_nvmem_map_buffer
(
u32
dst
,
u32
addrsz
,
u32
offset
,
u32
size
,
bool
w
)
{
void
*
ptr
;
void
*
rv
;
u32
map_times
=
addrsz
/
size
;
verify
((
addrsz
%
size
)
==
0
);
verify
(
map_times
>=
1
);
// This gets called whenever there is a pagefault, it is possible that it lands
// on the fpcb memory range, which is allocated on miss. Returning true tells the
// fault handler this was us, and that the page is resolved and can continue the execution.
bool
BM_LockedWrite
(
u8
*
address
)
{
if
(
!
virt_ram_base
)
return
false
;
// No vmem, therefore not us who caused this.
rv
=
MapViewOfFileEx
(
mem_handle
,
FILE_MAP_READ
|
(
w
?
FILE_MAP_WRITE
:
0
),
0
,
offset
,
size
,
&
virt_ram_base
[
dst
])
;
if
(
!
rv
)
return
0
;
uintptr_t
ptrint
=
(
uintptr_t
)
address
;
uintptr_t
start
=
(
uintptr_t
)
p_sh4rcb
->
fpcb
;
uintptr_t
end
=
start
+
sizeof
(
p_sh4rcb
->
fpcb
)
;
for
(
u32
i
=
1
;
i
<
map_times
;
i
++
)
{
dst
+=
size
;
ptr
=
MapViewOfFileEx
(
mem_handle
,
FILE_MAP_READ
|
(
w
?
FILE_MAP_WRITE
:
0
),
0
,
offset
,
size
,
&
virt_ram_base
[
dst
]);
if
(
!
ptr
)
return
0
;
if
(
ptrint
>=
start
&&
ptrint
<
end
)
{
// Alloc the page then and initialize it to default values
void
*
aligned_addr
=
(
void
*
)(
ptrint
&
(
~
PAGE_MASK
));
vmem_platform_ondemand_page
(
aligned_addr
,
PAGE_SIZE
);
bm_vmem_pagefill
((
void
**
)
aligned_addr
,
PAGE_SIZE
);
return
true
;
}
return
rv
;
}
static
void
*
_nvmem_unused_buffer
(
u32
start
,
u32
end
)
{
void
*
ptr
=
VirtualAlloc
(
&
virt_ram_base
[
start
],
end
-
start
,
MEM_RESERVE
,
PAGE_NOACCESS
);
if
(
ptr
==
0
)
return
0
;
return
ptr
;
}
static
void
*
_nvmem_alloc_mem
(
void
)
{
mem_handle
=
CreateFileMapping
(
INVALID_HANDLE_VALUE
,
0
,
PAGE_READWRITE
,
0
,
RAM_SIZE
+
VRAM_SIZE
+
ARAM_SIZE
,
0
);
void
*
rv
=
(
u8
*
)
VirtualAlloc
(
0
,
512
*
1024
*
1024
+
sizeof
(
Sh4RCB
)
+
ARAM_SIZE
,
MEM_RESERVE
,
PAGE_NOACCESS
);
if
(
rv
)
VirtualFree
(
rv
,
0
,
MEM_RELEASE
);
return
rv
;
}
#else
#ifndef MAP_NOSYNC
#define MAP_NOSYNC 0 //missing from linux :/ -- could be the cause of android slowness ?
#endif
#ifdef ANDROID
#include <linux/ashmem.h>
#ifndef ASHMEM_DEVICE
#define ASHMEM_DEVICE "/dev/ashmem"
#endif
int
ashmem_create_region
(
const
char
*
name
,
size_t
size
)
{
int
fd
,
ret
;
fd
=
open
(
ASHMEM_DEVICE
,
O_RDWR
);
if
(
fd
<
0
)
return
fd
;
if
(
name
)
{
char
buf
[
ASHMEM_NAME_LEN
];
strlcpy
(
buf
,
name
,
sizeof
(
buf
));
ret
=
ioctl
(
fd
,
ASHMEM_SET_NAME
,
buf
);
if
(
ret
<
0
)
goto
error
;
}
ret
=
ioctl
(
fd
,
ASHMEM_SET_SIZE
,
size
);
if
(
ret
<
0
)
goto
error
;
return
fd
;
error:
close
(
fd
);
return
ret
;
}
#endif
int
vmem_fd
;
static
void
*
_nvmem_unused_buffer
(
u32
start
,
u32
end
)
{
void
*
ptr
=
mmap
(
&
virt_ram_base
[
start
],
end
-
start
,
PROT_NONE
,
MAP_FIXED
|
MAP_PRIVATE
|
MAP_ANON
,
-
1
,
0
);
if
(
MAP_FAILED
==
ptr
)
{
printf
(
"nvmem_unused_buffer failed!
\n
"
);
return
0
;
}
return
ptr
;
}
static
void
*
_nvmem_map_buffer
(
u32
dst
,
u32
addrsz
,
u32
offset
,
u32
size
,
bool
w
)
{
void
*
ptr
;
void
*
rv
;
printf
(
"MAP %08X w/ %d
\n
"
,
dst
,
offset
);
u32
map_times
=
addrsz
/
size
;
verify
((
addrsz
%
size
)
==
0
);
verify
(
map_times
>=
1
);
u32
prot
=
PROT_READ
|
(
w
?
PROT_WRITE
:
0
);
rv
=
mmap
(
&
virt_ram_base
[
dst
],
size
,
prot
,
MAP_SHARED
|
MAP_NOSYNC
|
MAP_FIXED
,
vmem_fd
,
offset
);
if
(
MAP_FAILED
==
rv
||
rv
!=
(
void
*
)
&
virt_ram_base
[
dst
]
||
(
mprotect
(
rv
,
size
,
prot
)
!=
0
))
{
printf
(
"MAP1 failed %d
\n
"
,
errno
);
return
0
;
}
for
(
u32
i
=
1
;
i
<
map_times
;
i
++
)
{
dst
+=
size
;
ptr
=
mmap
(
&
virt_ram_base
[
dst
],
size
,
prot
,
MAP_SHARED
|
MAP_NOSYNC
|
MAP_FIXED
,
vmem_fd
,
offset
);
if
(
MAP_FAILED
==
ptr
||
ptr
!=
(
void
*
)
&
virt_ram_base
[
dst
]
||
(
mprotect
(
rv
,
size
,
prot
)
!=
0
))
{
printf
(
"MAP2 failed %d
\n
"
,
errno
);
return
0
;
}
}
return
rv
;
}
static
void
*
_nvmem_alloc_mem
(
void
)
{
string
path
=
get_writable_data_path
(
"dcnzorz_mem"
);
#ifdef __MACH__
vmem_fd
=
open
(
path
.
c_str
(),
O_CREAT
|
O_RDWR
|
O_TRUNC
,
S_IRWXU
|
S_IRWXG
|
S_IRWXO
);
unlink
(
path
.
c_str
());
#elif defined(ANDROID)
vmem_fd
=
ashmem_create_region
(
0
,
RAM_SIZE
+
VRAM_SIZE
+
ARAM_SIZE
);
#else
vmem_fd
=
shm_open
(
path
.
c_str
(),
O_CREAT
|
O_EXCL
|
O_RDWR
,
S_IREAD
|
S_IWRITE
);
shm_unlink
(
path
.
c_str
());
if
(
vmem_fd
==-
1
)
{
vmem_fd
=
open
(
path
.
c_str
(),
O_CREAT
|
O_RDWR
|
O_TRUNC
,
S_IRWXU
|
S_IRWXG
|
S_IRWXO
);
unlink
(
path
.
c_str
());
}
#endif
#if defined(__MACH__) || !defined(ANDROID)
verify
(
ftruncate
(
vmem_fd
,
RAM_SIZE
+
VRAM_SIZE
+
ARAM_SIZE
)
==
0
);
#endif
u32
sz
=
512
*
1024
*
1024
+
sizeof
(
Sh4RCB
)
+
ARAM_SIZE
+
0x10000
;
void
*
rv
=
mmap
(
0
,
sz
,
PROT_NONE
,
MAP_PRIVATE
|
MAP_ANON
,
-
1
,
0
);
verify
(
rv
!=
NULL
);
munmap
(
rv
,
sz
);
return
(
u8
*
)
rv
+
0x10000
-
size_t
(
rv
)
%
0x10000
;
//align to 64 KB (Needed for linaro mmap not to extend to next region)
}
#endif
#define map_buffer(dsts,dste,offset,sz,w) {ptr=_nvmem_map_buffer(dsts,dste-dsts,offset,sz,w);if (!ptr) return false;}
#define unused_buffer(start,end) {ptr=_nvmem_unused_buffer(start,end);if (!ptr) return false;}
u32
pagecnt
;
void
_vmem_bm_reset_nvmem
(
void
)
{
#if defined(TARGET_NO_NVMEM)
return
;
#endif
#ifdef IOS
/* On iOS & nacl we allways allocate all of the mapping table */
mprotect
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
PROT_READ
|
PROT_WRITE
);
return
;
#endif
pagecnt
=
0
;
#ifdef _WIN32
VirtualFree
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
MEM_DECOMMIT
);
#else
mprotect
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
PROT_NONE
);
#ifdef __HAIKU__
posix_madvise
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
POSIX_MADV_DONTNEED
);
#else
madvise
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
MADV_DONTNEED
);
#endif
#ifdef MADV_REMOVE
madvise
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
MADV_REMOVE
);
#else
#ifdef __HAIKU__
posix_madvise
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
POSIX_MADV_DONTNEED
);
#else
/* OSX, IOS */
madvise
(
p_sh4rcb
,
sizeof
(
p_sh4rcb
->
fpcb
),
MADV_FREE
);
#endif
#endif
#endif
printf
(
"Freeing fpcb
\n
"
);
return
false
;
}
bool
BM_LockedWrite
(
u8
*
address
)
static
void
_vmem_set_p0_mappings
(
)
{
if
(
!
_nvmem_enabled
())
return
false
;
#if FEAT_SHREC != DYNAREC_NONE
size_t
addr
=
address
-
(
u8
*
)
p_sh4rcb
->
fpcb
;
address
=
(
u8
*
)
p_sh4rcb
->
fpcb
+
(
addr
&~
SH4_PAGE_MASK
);
if
(
addr
<
sizeof
(
p_sh4rcb
->
fpcb
))
{
//printf("Allocated %d PAGES [%08X]\n",++pagecnt,addr);
#ifdef _WIN32
verify
(
VirtualAlloc
(
address
,
PAGE_SIZE
,
MEM_COMMIT
,
PAGE_READWRITE
));
#else
mprotect
(
address
,
PAGE_SIZE
,
PROT_READ
|
PROT_WRITE
);
#endif
bm_vmem_pagefill
((
void
**
)
address
,
PAGE_SIZE
);
return
true
;
}
#else
die
(
"BM_LockedWrite and NO REC"
);
#endif
return
false
;
const
vmem_mapping
mem_mappings
[]
=
{
// P0/U0
{
0x00000000
,
0x00800000
,
0
,
0
,
false
},
// Area 0 -> unused
{
0x00800000
,
0x00800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica
{
0x00800000
+
ARAM_SIZE
,
0x02800000
,
0
,
0
,
false
},
// unused
{
0x02800000
,
0x02800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica mirror
{
0x02800000
+
ARAM_SIZE
,
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
,
0x0C000000
,
0
,
0
,
false
},
// Area 2
{
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
(
void
)
{
void
*
ptr
=
0
;
verify
((
sizeof
(
Sh4RCB
)
%
PAGE_SIZE
)
==
0
);
if
(
settings
.
dynarec
.
disable_nvmem
)
return
_vmem_reserve_nonvmem
();
virt_ram_base
=
(
u8
*
)
_nvmem_alloc_mem
();
if
(
virt_ram_base
==
0
)
return
_vmem_reserve_nonvmem
();
p_sh4rcb
=
(
Sh4RCB
*
)
virt_ram_base
;
#ifdef _WIN32
verify
(
p_sh4rcb
==
VirtualAlloc
(
p_sh4rcb
,
sizeof
(
Sh4RCB
),
MEM_RESERVE
,
PAGE_NOACCESS
));
verify
(
VirtualAlloc
((
u8
*
)
p_sh4rcb
+
sizeof
(
p_sh4rcb
->
fpcb
),
sizeof
(
Sh4RCB
)
-
sizeof
(
p_sh4rcb
->
fpcb
),
MEM_COMMIT
,
PAGE_READWRITE
));
#else
void
*
ret
=
mmap
(
p_sh4rcb
,
sizeof
(
Sh4RCB
),
PROT_READ
|
PROT_WRITE
,
MAP_PRIVATE
|
MAP_ANON
,
-
1
,
0
);
verify
(
p_sh4rcb
==
ret
);
#endif
virt_ram_base
+=
sizeof
(
Sh4RCB
);
//Area 0
//[0x00000000 ,0x00800000) -> unused
unused_buffer
(
0x00000000
,
0x00800000
);
//I wonder, aica ram warps here ?.?
//I really should check teh docs before codin ;p
//[0x00800000,0x00A00000);
map_buffer
(
0x00800000
,
0x01000000
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
false
);
map_buffer
(
0x20000000
,
0x20000000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
);
aica_ram
.
size
=
ARAM_SIZE
;
aica_ram
.
data
=
(
u8
*
)
ptr
;
//[0x01000000 ,0x04000000) -> unused
unused_buffer
(
0x01000000
,
0x04000000
);
VMemType
vmemstatus
=
MemTypeError
;
//Area 1
//[0x04000000,0x05000000) -> vram (16mb, warped on dc)
map_buffer
(
0x04000000
,
0x05000000
,
MAP_VRAM_START_OFFSET
,
VRAM_SIZE
,
true
);
// Use vmem only if settings mandate so, and if we have proper exception handlers.
#ifndef TARGET_NO_EXCEPTIONS
if
(
!
settings
.
dynarec
.
disable_nvmem
)
vmemstatus
=
vmem_platform_init
((
void
**
)
&
virt_ram_base
,
(
void
**
)
&
p_sh4rcb
);
#endif
vram
.
size
=
VRAM_SIZE
;
vram
.
data
=
(
u8
*
)
ptr
;
// Fallback to statically allocated buffers, this results in slow-ops being generated.
if
(
vmemstatus
==
MemTypeError
)
{
printf
(
"Warning! nvmem is DISABLED (due to failure or not being built-in
\n
"
);
virt_ram_base
=
0
;
//[0x05000000,0x06000000) -> unused (32b path)
unused_buffer
(
0x05000000
,
0x06000000
);
// Allocate it all and initialize it.
p_sh4rcb
=
(
Sh4RCB
*
)
malloc_pages
(
sizeof
(
Sh4RCB
));
bm_vmem_pagefill
((
void
**
)
p_sh4rcb
->
fpcb
,
sizeof
(
p_sh4rcb
->
fpcb
));
//[0x06000000,0x07000000) -> vram mirror
m
ap_buffer
(
0x06000000
,
0x07000000
,
MAP_VRAM_START_OFFSET
,
V
RAM_SIZE
,
true
);
mem_b
.
size
=
RAM_SIZE
;
m
em_b
.
data
=
(
u8
*
)
malloc_pages
(
RAM_SIZE
);
vram
.
size
=
VRAM_SIZE
;
vram
.
data
=
(
u8
*
)
malloc_pages
(
VRAM_SIZE
);
//[0x07000000,0x08000000) -> unused (32b path) mirror
unused_buffer
(
0x07000000
,
0x08000000
);
//Area 2
//[0x08000000,0x0C000000) -> unused
unused_buffer
(
0x08000000
,
0x0C000000
);
//Area 3
//[0x0C000000,0x0D000000) -> main ram
//[0x0D000000,0x0E000000) -> main ram mirror
//[0x0E000000,0x0F000000) -> main ram mirror
//[0x0F000000,0x10000000) -> main ram mirror
map_buffer
(
0x0C000000
,
0x10000000
,
MAP_RAM_START_OFFSET
,
RAM_SIZE
,
true
);
mem_b
.
size
=
RAM_SIZE
;
mem_b
.
data
=
(
u8
*
)
ptr
;
//Area 4
//Area 5
//Area 6
//Area 7
//all -> Unused
//[0x10000000,0x20000000) -> unused
unused_buffer
(
0x10000000
,
0x20000000
);
aica_ram
.
size
=
ARAM_SIZE
;
aica_ram
.
data
=
(
u8
*
)
malloc_pages
(
ARAM_SIZE
);
}
else
{
printf
(
"Info: nvmem is enabled, with addr space of size %s
\n
"
,
vmemstatus
==
MemType4GB
?
"4GB"
:
"512MB"
);
printf
(
"Info: p_sh4rcb: %p virt_ram_base: %p
\n
"
,
p_sh4rcb
,
virt_ram_base
);
// Map the different parts of the memory file into the new memory range we got.
if
(
vmemstatus
==
MemType512MB
)
{
vmem_mapping
mem_mappings
[]
=
{
{
0x00000000
,
0x00800000
,
0
,
0
,
false
},
// Area 0 -> unused
{
0x00800000
,
0x01000000
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
false
},
// Aica
{
0x20000000
,
0x20000000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
{
0x01000000
,
0x04000000
,
0
,
0
,
false
},
// More 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
,
0x0C000000
,
0
,
0
,
false
},
// Area 2
{
0x0C000000
,
0x10000000
,
MAP_RAM_START_OFFSET
,
RAM_SIZE
,
true
},
// Area 3 (main RAM + 3 mirrors)
{
0x10000000
,
0x20000000
,
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
[
0x20000000
];
// Points to the writable AICA addrspace
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
}
else
{
_vmem_set_p0_mappings
();
const
vmem_mapping
mem_mappings
[]
=
{
// P1
{
0x80000000
,
0x80800000
,
0
,
0
,
false
},
// Area 0 -> unused
{
0x80800000
,
0x80800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica
{
0x80800000
+
ARAM_SIZE
,
0x82800000
,
0
,
0
,
false
},
// unused
{
0x82800000
,
0x82800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica mirror
{
0x82800000
+
ARAM_SIZE
,
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
,
0x8C000000
,
0
,
0
,
false
},
// Area 2
{
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
,
0xA0800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica
{
0xA0800000
+
ARAM_SIZE
,
0xA2800000
,
0
,
0
,
false
},
// unused
{
0xA2800000
,
0xA2800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica mirror
{
0xA2800000
+
ARAM_SIZE
,
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
,
0xAC000000
,
0
,
0
,
false
},
// Area 2
{
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
,
0xC0800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica
{
0xC0800000
+
ARAM_SIZE
,
0xC2800000
,
0
,
0
,
false
},
// unused
{
0xC2800000
,
0xC2800000
+
ARAM_SIZE
,
MAP_ARAM_START_OFFSET
,
ARAM_SIZE
,
true
},
// Aica mirror
{
0xC2800000
+
ARAM_SIZE
,
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