- added SIGSEGV support for Linux/Alpha (to be checked), Darwin/PPC

- added uniform virtual memory allocation
  (supports mmap(), vm_allocate(), or fallbacks to malloc()/free())
- cleaned up memory allocation in main_unix.cpp
This commit is contained in:
gbeauche 2001-06-26 22:35:42 +00:00
parent 673c53231f
commit dae4fb627c
12 changed files with 778 additions and 184 deletions

View File

@ -2,6 +2,8 @@ Bugs:
- System 7.1 with Quadra900 ModelID (1MB ROM): 0x108 gets strange value
- Real memory addressing: something is still wrong in the Unix part, though
it works under Linux/i386
- VOSF does not work with Darwin/X11. Probably due to a combination of
select()/signals/sigsegv handling/vm_protect()
General:
- Sony: rdVerify, Tag Buffer
@ -35,7 +37,6 @@ BeOS:
- Last sound buffer is not played
Unix:
- video_vosf.h: check correctness of {15,16,24 bpp} blitters on big endian systems
- clip_unix.cpp: clip Unix->Basilisk
- clip_unix.cpp: use X selections instead of cut buffer
- sys_unix.cpp: SysFormat(), SysIsFixedDisk(), SysIsDiskInserted(), prevent/allow

View File

@ -33,7 +33,7 @@ SRCS = ../main.cpp main_unix.cpp ../prefs.cpp ../prefs_items.cpp prefs_unix.cpp
../emul_op.cpp ../macos_util.cpp ../xpram.cpp xpram_unix.cpp ../timer.cpp \
timer_unix.cpp clip_unix.cpp ../adb.cpp ../serial.cpp ../ether.cpp \
../sony.cpp ../disk.cpp ../cdrom.cpp ../scsi.cpp ../video.cpp video_blit.cpp \
video_x.cpp sigsegv.cpp ../audio.cpp ../extfs.cpp extfs_unix.cpp \
video_x.cpp vm_alloc.cpp sigsegv.cpp ../audio.cpp ../extfs.cpp extfs_unix.cpp \
../user_strings.cpp user_strings_unix.cpp \
$(SYSSRCS) $(CPUSRCS)
APP = BasiliskII

View File

@ -56,6 +56,18 @@
/* Define if we know a hack to replace siginfo_t::si_addr member */
#undef HAVE_SIGCONTEXT_SUBTERFUGE
/* Define if your system has a working vm_allocate()-based memory allocator */
#undef HAVE_MACH_VM
/* Define if your system has a working mmap()-based memory allocator */
#undef HAVE_MMAP_VM
/* Define if <sys/mman.h> defines MAP_ANON and mmap()'ing with MAP_ANON works */
#undef HAVE_MMAP_ANON
/* Define if <sys/mman.h> defines MAP_ANONYMOUS and mmap()'ing with MAP_ANONYMOUS works */
#undef HAVE_MMAP_ANONYMOUS
/* Leave that blank line there!! Autoheader needs it.
If you're adding to this file, keep in mind:

View File

@ -52,7 +52,8 @@ case "$target_os" in
netbsd*) OS_TYPE=netbsd;;
freebsd*) OS_TYPE=freebsd;;
solaris*) OS_TYPE=solaris;;
*) OS_TYPE=`echo $target_os | sed -e 's/-/_/' | sed -e 's/\./_/'`;;
darwin*) OS_TYPE=darwin;;
*) OS_TYPE=`echo $target_os | sed -e 's/-/_/g' | sed -e 's/\./_/g'`;;
esac
DEFINES="$DEFINES -DOS_$OS_TYPE"
@ -66,7 +67,7 @@ case "$target_cpu" in
m68k* ) CPU_TYPE=m68k HAVE_M68K=yes;;
sparc* ) CPU_TYPE=sparc HAVE_SPARC=yes;;
powerpc* ) CPU_TYPE=powerpc HAVE_POWERPC=yes;;
*) CPU_TYPE=`echo $target_cpu | sed -e 's/-/_/'`;;
*) CPU_TYPE=`echo $target_cpu | sed -e 's/-/_/g'`;;
esac
DEFINES="$DEFINES -DCPU_$CPU_TYPE"
@ -191,7 +192,7 @@ fi
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h fcntl.h sys/time.h)
AC_CHECK_HEADERS(unistd.h fcntl.h sys/time.h sys/mman.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_BIGENDIAN
@ -213,6 +214,11 @@ dnl Checks for library functions.
AC_CHECK_FUNCS(strdup cfmakeraw)
AC_CHECK_FUNCS(clock_gettime timer_create)
AC_CHECK_FUNCS(sigaction signal)
AC_CHECK_FUNCS(mmap mprotect munmap)
AC_CHECK_FUNCS(vm_allocate vm_deallocate vm_protect)
dnl Darwin seems to define mach_task_self() instead of task_self().
AC_CHECK_FUNCS(mach_task_self task_self)
dnl Select system-dependant source files.
SERIALSRC=serial_unix.cpp
@ -297,33 +303,169 @@ dnl to be put into the config.h file
dnl $1 -- the macro to define
dnl $2 -- the value to translate
AC_DEFUN(AC_TRANSLATE_DEFINE, [
if [[ "x$2" = "xyes" ]]; then
if [[ "x$2" = "xyes" -o "x$2" = "xguessing yes" ]]; then
AC_DEFINE($1)
fi
])
dnl Various checks if the system supports vm_allocate() and the like functions.
have_mach_vm=no
if [[ "x$ac_cv_func_vm_allocate" = "xyes" -a "x$ac_cv_func_vm_deallocate" = "xyes" -a \
"x$ac_cv_func_vm_protect" = "xyes" ]]; then
have_mach_vm=yes
fi
AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm")
dnl Check that vm_allocate(), vm_protect() work
if [[ "x$have_mach_vm" = "xyes" ]]; then
AC_CACHE_CHECK("whether vm_protect works",
ac_cv_vm_protect_works, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
ac_cv_vm_protect_works=yes
dnl First the tests that should segfault
for test_def in NONE_READ NONE_WRITE READ_WRITE; do
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_$test_def
#include "vm_alloc.cpp"
], ac_cv_vm_protect_works=no, rm -f core,
dnl When cross-compiling, do not assume anything
ac_cv_vm_protect_works="guessing no"
)
done
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_RDWR_WRITE
#include "vm_alloc.cpp"
], , ac_cv_vm_protect_works=no,
dnl When cross-compiling, do not assume anything
ac_cv_vm_protect_works="guessing no"
)
AC_LANG_RESTORE
]
)
dnl Remove support for vm_allocate() if vm_protect() does not work
if [[ "x$have_mach_vm" = "xyes" ]]; then
case $ac_cv_vm_protect_works in
*yes) have_mach_vm=yes;;
*no) have_mach_vm=no;;
esac
fi
AC_TRANSLATE_DEFINE(HAVE_MACH_VM, "$have_mach_vm")
fi dnl HAVE_MACH_VM
dnl Various checks if the system supports mmap() and the like functions.
dnl ... and Mach memory allocators are not supported
have_mmap_vm=no
if [[ "x$ac_cv_func_mmap" = "xyes" -a "x$ac_cv_func_munmap" = "xyes" -a \
"x$ac_cv_func_mprotect" = "xyes" ]]; then
if [[ "x$have_mach_vm" = "xno" ]]; then
have_mmap_vm=yes
fi
fi
AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, "$have_mmap_vm")
dnl Check that mmap() and associated functions work.
if [[ "x$have_mmap_vm" = "xyes" ]]; then
dnl Check if we have a working anonymous mmap()
AC_CACHE_CHECK("whether mmap supports MAP_ANON",
ac_cv_mmap_anon, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_MMAP_ANON
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_MMAP_ANON
#include "vm_alloc.cpp"
], ac_cv_mmap_anon=yes, ac_cv_mmap_anon=no,
dnl When cross-compiling, do not assume anything.
ac_cv_mmap_anon="guessing no"
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(HAVE_MMAP_ANON, "$ac_cv_mmap_anon")
AC_CACHE_CHECK("whether mmap supports MAP_ANONYMOUS",
ac_cv_mmap_anonymous, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_MMAP_ANONYMOUS
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_MMAP_ANON
#include "vm_alloc.cpp"
], ac_cv_mmap_anonymous=yes, ac_cv_mmap_anonymous=no,
dnl When cross-compiling, do not assume anything.
ac_cv_mmap_anonymous="guessing no"
)
AC_LANG_RESTORE
]
)
AC_TRANSLATE_DEFINE(HAVE_MMAP_ANONYMOUS, "$ac_cv_mmap_anonymous")
AC_CACHE_CHECK("whether mprotect works",
ac_cv_mprotect_works, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
ac_cv_mprotect_works=yes
dnl First the tests that should segfault
for test_def in NONE_READ NONE_WRITE READ_WRITE; do
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_$test_def
#include "vm_alloc.cpp"
], ac_cv_mprotect_works=no, rm -f core,
dnl When cross-compiling, do not assume anything
ac_cv_mprotect_works="guessing no"
)
done
AC_TRY_RUN([
#define CONFIGURE_TEST_VM_MAP
#define TEST_VM_PROT_RDWR_WRITE
#include "vm_alloc.cpp"
], , ac_cv_mprotect_works=no,
dnl When cross-compiling, do not assume anything
ac_cv_mprotect_works="guessing no"
)
AC_LANG_RESTORE
]
)
dnl Remove support for mmap() if mprotect() does not work
if [[ "x$have_mmap_vm" = "xyes" ]]; then
case $ac_cv_mprotect_works in
*yes) have_mmap_vm=yes;;
*no) have_mmap_vm=no;;
esac
fi
AC_TRANSLATE_DEFINE(HAVE_MMAP_VM, $have_mmap_vm)
fi dnl HAVE_MMAP_VM
dnl Check if we can mmap 0x2000 bytes from 0x0000
AC_CACHE_CHECK("whether we can map Low Memory area 0x0000-0x2000",
ac_cv_can_map_lm, [
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
int main()
{ int zero_fd; char * lm;
if ((zero_fd = open("/dev/zero", O_RDWR)) < 0) exit(1);
if ((lm = (char *)mmap((caddr_t)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0)) == MAP_FAILED) exit(1);
lm[0] = 0x12;
munmap(lm, 0x2000);
close(zero_fd);
exit(0);
#include "vm_alloc.cpp"
int main(void) { /* returns 0 if we could map the lowmem globals */
volatile char * lm;
if (vm_init() < 0) exit(1);
if ((lm = (volatile char *)vm_acquire_fixed(0, 0x2000)) == VM_MAP_FAILED) exit(1);
lm[0] = 'z';
if (vm_release((char *)lm, 0x2000) < 0) exit(1);
vm_exit(); exit(0);
}
],
[ac_cv_can_map_lm=yes],
[ac_cv_can_map_lm=no]
], ac_cv_can_map_lm=yes, ac_cv_can_map_lm=no,
dnl When cross-compiling, do not assume anything.
ac_cv_can_map_lm="guessing no"
)
AC_LANG_RESTORE
]
@ -346,9 +488,9 @@ AC_CACHE_CHECK("whether signal handlers need to be reinstalled",
signal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1);
exit(handled_signal == 2);
}
],
[ac_cv_signal_need_reinstall=yes],
[ac_cv_signal_need_reinstall=no]
], ac_cv_signal_need_reinstall=yes, ac_cv_signal_need_reinstall=no,
dnl When cross-compiling, do not assume anything.
ac_cv_signal_need_reinstall="guessing yes"
)
AC_LANG_RESTORE
]
@ -379,9 +521,9 @@ AC_CACHE_CHECK("whether sigaction handlers need to be reinstalled",
mysignal(SIGUSR1, sigusr1_handler); raise(SIGUSR1); raise(SIGUSR1);
exit(handled_signal == 2);
}
],
[ac_cv_sigaction_need_reinstall=yes],
[ac_cv_sigaction_need_reinstall=no]
], ac_cv_sigaction_need_reinstall=yes, ac_cv_sigaction_need_reinstall=no,
dnl When cross-compiling, do not assume anything.
ac_cv_sigaction_need_reinstall="guessing yes"
)
AC_LANG_RESTORE
]
@ -395,11 +537,12 @@ AC_CACHE_CHECK("whether your system supports extended signal handlers",
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_SIGINFO_T 1
#define CONFIGURE_TEST
#define CONFIGURE_TEST_SIGSEGV_RECOVERY
#include "vm_alloc.cpp"
#include "sigsegv.cpp"
],
[ac_cv_have_extended_signals=yes],
[ac_cv_have_extended_signals=no]
], ac_cv_have_extended_signals=yes, ac_cv_have_extended_signals=no,
dnl When cross-compiling, do not assume anything.
ac_cv_have_extended_signals=no
)
AC_LANG_RESTORE
]
@ -414,11 +557,12 @@ if [[ "x$ac_cv_have_extended_signals" = "xno" ]]; then
AC_LANG_CPLUSPLUS
AC_TRY_RUN([
#define HAVE_SIGCONTEXT_SUBTERFUGE 1
#define CONFIGURE_TEST
#define CONFIGURE_TEST_SIGSEGV_RECOVERY
#include "vm_alloc.cpp"
#include "sigsegv.cpp"
],
[ac_cv_have_sigcontext_hack=yes],
[ac_cv_have_sigcontext_hack=no]
], ac_cv_have_sigcontext_hack=yes, ac_cv_have_sigcontext_hack=no,
dnl When cross-compiling, do not assume anything.
ac_cv_have_sigcontext_hack=no
)
AC_LANG_RESTORE
])

View File

@ -71,6 +71,7 @@ struct sigstate {
#include "user_strings.h"
#include "version.h"
#include "main.h"
#include "vm_alloc.h"
#ifdef ENABLE_MON
# include "mon.h"
@ -108,7 +109,6 @@ bool TwentyFourBitAddressing;
char *x_display_name = NULL; // X11 display name
Display *x_display = NULL; // X11 display handle
static int zero_fd = -1; // FD of /dev/zero
static uint8 last_xpram[256]; // Buffer for monitoring XPRAM changes
#ifdef HAVE_PTHREADS
@ -154,11 +154,6 @@ static void sigint_handler(...);
#if REAL_ADDRESSING
static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
static bool memory_mapped_from_zero = false; // Flag: Could allocate RAM area from 0
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
static uint32 mapped_ram_rom_size; // Total size of mmap()ed RAM/ROM area
#endif
@ -272,14 +267,6 @@ int main(int argc, char **argv)
if (!PrefsEditor())
QuitEmulator();
// Open /dev/zero
zero_fd = open("/dev/zero", O_RDWR);
if (zero_fd < 0) {
sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
// Read RAM size
RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
if (RAMSize < 1024*1024) {
@ -288,32 +275,37 @@ int main(int argc, char **argv)
}
#if REAL_ADDRESSING || DIRECT_ADDRESSING
const uint32 page_size = getpagesize();
const uint32 page_mask = page_size - 1;
const uint32 aligned_ram_size = (RAMSize + page_mask) & ~page_mask;
mapped_ram_rom_size = aligned_ram_size + 0x100000;
RAMSize = RAMSize & -getpagesize(); // Round down to page boundary
#endif
// Initialize VM system
vm_init();
#if REAL_ADDRESSING
// Try to allocate the complete address space from zero
// gb-- the Solaris manpage about mmap(2) states that using MAP_FIXED
// implies undefined behaviour for further use of sbrk(), malloc(), etc.
// cebix-- on NetBSD/m68k, this causes a segfault
// Flag: RAM and ROM are contigously allocated from address 0
bool memory_mapped_from_zero = false;
// Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
// when trying to map a too big chunk of memory starting at address 0
#if defined(OS_solaris) || defined(OS_netbsd)
// Anyway, it doesn't work...
if (0) {
const bool can_map_all_memory = false;
#else
if (mmap((caddr_t)0x0000, mapped_ram_rom_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) != MAP_FAILED) {
const bool can_map_all_memory = true;
#endif
// Try to allocate all memory from 0x0000, if it is not known to crash
if (can_map_all_memory && (vm_acquire_fixed(0, RAMSize + 0x100000) == 0)) {
D(bug("Could allocate RAM and ROM from 0x0000\n"));
memory_mapped_from_zero = true;
}
// Create Low Memory area (0x0000..0x2000)
else if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) != MAP_FAILED) {
// Otherwise, just create the Low Memory area (0x0000..0x2000)
else if (vm_acquire_fixed(0, 0x2000) == 0) {
D(bug("Could allocate the Low Memory globals\n"));
lm_area_mapped = true;
}
// Exit on error
// Exit on failure
else {
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
ErrorAlert(str);
@ -323,8 +315,8 @@ int main(int argc, char **argv)
#if USE_SCRATCHMEM_SUBTERFUGE
// Allocate scratch memory
ScratchMem = (uint8 *)malloc(SCRATCH_MEM_SIZE);
if (ScratchMem == NULL) {
ScratchMem = (uint8 *)vm_acquire(SCRATCH_MEM_SIZE);
if (ScratchMem == VM_MAP_FAILED) {
ErrorAlert(GetString(STR_NO_MEM_ERR));
QuitEmulator();
}
@ -332,41 +324,29 @@ int main(int argc, char **argv)
#endif
// Create areas for Mac RAM and ROM
#if REAL_ADDRESSING || DIRECT_ADDRESSING
// gb-- Overkill, needs to be cleaned up. Probably explode it for either
// real or direct addressing mode.
#if REAL_ADDRESSING
if (memory_mapped_from_zero) {
RAMBaseHost = (uint8 *)0;
ROMBaseHost = RAMBaseHost + aligned_ram_size;
ROMBaseHost = RAMBaseHost + RAMSize;
}
else
#endif
{
RAMBaseHost = (uint8 *)mmap(0, mapped_ram_rom_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
if (RAMBaseHost == (uint8 *)MAP_FAILED) {
RAMBaseHost = (uint8 *)vm_acquire(RAMSize);
ROMBaseHost = (uint8 *)vm_acquire(0x100000);
if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
ErrorAlert(GetString(STR_NO_MEM_ERR));
QuitEmulator();
}
ROMBaseHost = RAMBaseHost + aligned_ram_size;
}
#else
RAMBaseHost = (uint8 *)malloc(RAMSize);
ROMBaseHost = (uint8 *)malloc(0x100000);
if (RAMBaseHost == NULL || ROMBaseHost == NULL) {
ErrorAlert(GetString(STR_NO_MEM_ERR));
QuitEmulator();
}
#endif
#if DIRECT_ADDRESSING
// Initialize MEMBaseDiff now so that Host2MacAddr in the Video module
// will return correct results
// RAMBaseMac shall always be zero
MEMBaseDiff = (uintptr)RAMBaseHost;
RAMBaseMac = 0;
ROMBaseMac = RAMBaseMac + aligned_ram_size;
InitMEMBaseDiff(RAMBaseHost, RAMBaseMac);
ROMBaseMac = Host2MacAddr(ROMBaseHost);
#endif
#if REAL_ADDRESSING // && !EMULATED_68K
#if REAL_ADDRESSING
RAMBaseMac = (uint32)RAMBaseHost;
ROMBaseMac = (uint32)ROMBaseHost;
#endif
@ -623,31 +603,19 @@ void QuitEmulator(void)
ExitAll();
// Free ROM/RAM areas
#if REAL_ADDRESSING
if (memory_mapped_from_zero)
munmap((caddr_t)0x0000, mapped_ram_rom_size);
else
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
if (RAMBaseHost != (uint8 *)MAP_FAILED) {
munmap((caddr_t)RAMBaseHost, mapped_ram_rom_size);
if (RAMBaseHost != VM_MAP_FAILED) {
vm_release(RAMBaseHost, RAMSize);
RAMBaseHost = NULL;
}
#else
if (ROMBaseHost) {
free(ROMBaseHost);
if (ROMBaseHost != VM_MAP_FAILED) {
vm_release(ROMBaseHost, 0x100000);
ROMBaseHost = NULL;
}
if (RAMBaseHost) {
free(RAMBaseHost);
RAMBaseHost = NULL;
}
#endif
#if USE_SCRATCHMEM_SUBTERFUGE
// Delete scratch memory area
if (ScratchMem) {
free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
ScratchMem = NULL;
}
#endif
@ -655,12 +623,11 @@ void QuitEmulator(void)
#if REAL_ADDRESSING
// Delete Low Memory area
if (lm_area_mapped)
munmap((char *)0x0000, 0x2000);
vm_release(0, 0x2000);
#endif
// Close /dev/zero
if (zero_fd > 0)
close(zero_fd);
// Exit VM wrappers
vm_exit();
// Exit system routines
SysExit();

View File

@ -79,6 +79,21 @@ static bool sigsegv_do_install_handler(int sig);
#define SIGSEGV_FAULT_ADDRESS scp->regs->dar
#define SIGSEGV_FAULT_INSTRUCTION scp->regs->nip
#endif
#if (defined(alpha) || defined(__alpha__))
#include <asm/sigcontext.h>
#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
#define SIGSEGV_FAULT_INSTRUCTION scp->sc_pc
// From Boehm's GC 6.0alpha8
static sigsegv_address_t get_fault_address(struct sigcontext *scp)
{
unsigned int instruction = *((unsigned int *)(scp->sc_pc));
unsigned long fault_address = scp->sc_regs[(instruction >> 16) & 0x1f];
fault_address += (signed long)(signed short)(instruction & 0xffff);
return (sigsegv_address_t)fault_address;
}
#endif
#endif
// Irix 5 or 6 on MIPS
@ -132,6 +147,114 @@ static bool sigsegv_do_install_handler(int sig);
#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
#endif
#endif
// MacOS X
#if defined(__APPLE__) && defined(__MACH__)
#if (defined(ppc) || defined(__ppc__))
#define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp
#define SIGSEGV_FAULT_ADDRESS get_fault_address(scp)
#define SIGSEGV_FAULT_INSTRUCTION scp->sc_ir
#define SIGSEGV_ALL_SIGNALS FAULT_HANDLER(SIGBUS)
// From Boehm's GC 6.0alpha8
#define EXTRACT_OP1(iw) (((iw) & 0xFC000000) >> 26)
#define EXTRACT_OP2(iw) (((iw) & 0x000007FE) >> 1)
#define EXTRACT_REGA(iw) (((iw) & 0x001F0000) >> 16)
#define EXTRACT_REGB(iw) (((iw) & 0x03E00000) >> 21)
#define EXTRACT_REGC(iw) (((iw) & 0x0000F800) >> 11)
#define EXTRACT_DISP(iw) ((short *) &(iw))[1]
static sigsegv_address_t get_fault_address(struct sigcontext *scp)
{
unsigned int instr = *((unsigned int *) scp->sc_ir);
unsigned int * regs = &((unsigned int *) scp->sc_regs)[2];
int disp = 0, tmp;
unsigned int baseA = 0, baseB = 0;
unsigned int addr, alignmask = 0xFFFFFFFF;
switch(EXTRACT_OP1(instr)) {
case 38: /* stb */
case 39: /* stbu */
case 54: /* stfd */
case 55: /* stfdu */
case 52: /* stfs */
case 53: /* stfsu */
case 44: /* sth */
case 45: /* sthu */
case 47: /* stmw */
case 36: /* stw */
case 37: /* stwu */
tmp = EXTRACT_REGA(instr);
if(tmp > 0)
baseA = regs[tmp];
disp = EXTRACT_DISP(instr);
break;
case 31:
switch(EXTRACT_OP2(instr)) {
case 86: /* dcbf */
case 54: /* dcbst */
case 1014: /* dcbz */
case 247: /* stbux */
case 215: /* stbx */
case 759: /* stfdux */
case 727: /* stfdx */
case 983: /* stfiwx */
case 695: /* stfsux */
case 663: /* stfsx */
case 918: /* sthbrx */
case 439: /* sthux */
case 407: /* sthx */
case 661: /* stswx */
case 662: /* stwbrx */
case 150: /* stwcx. */
case 183: /* stwux */
case 151: /* stwx */
case 135: /* stvebx */
case 167: /* stvehx */
case 199: /* stvewx */
case 231: /* stvx */
case 487: /* stvxl */
tmp = EXTRACT_REGA(instr);
if(tmp > 0)
baseA = regs[tmp];
baseB = regs[EXTRACT_REGC(instr)];
/* determine Altivec alignment mask */
switch(EXTRACT_OP2(instr)) {
case 167: /* stvehx */
alignmask = 0xFFFFFFFE;
break;
case 199: /* stvewx */
alignmask = 0xFFFFFFFC;
break;
case 231: /* stvx */
alignmask = 0xFFFFFFF0;
break;
case 487: /* stvxl */
alignmask = 0xFFFFFFF0;
break;
}
break;
case 725: /* stswi */
tmp = EXTRACT_REGA(instr);
if(tmp > 0)
baseA = regs[tmp];
break;
default: /* ignore instruction */
return 0;
break;
}
break;
default: /* ignore instruction */
return 0;
break;
}
addr = (baseA + baseB) + disp;
addr &= alignmask;
return (sigsegv_address_t)addr;
}
#endif
#endif
#endif
// Fallbacks
@ -243,12 +366,12 @@ void sigsegv_deinstall_handler(void)
* Test program used for configure/test
*/
#ifdef CONFIGURE_TEST
#ifdef CONFIGURE_TEST_SIGSEGV_RECOVERY
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "vm_alloc.h"
static int page_size;
static volatile char * page = 0;
@ -259,20 +382,21 @@ static bool sigsegv_test_handler(sigsegv_address_t fault_address, sigsegv_addres
handler_called++;
if ((fault_address - 123) != page)
exit(1);
if (mprotect((char *)((unsigned long)fault_address & -page_size), page_size, PROT_READ | PROT_WRITE) != 0)
if (vm_protect((char *)((unsigned long)fault_address & -page_size), page_size, VM_PAGE_READ | VM_PAGE_WRITE) != 0)
exit(1);
return true;
}
int main(void)
{
int zero_fd = open("/dev/zero", O_RDWR);
if (zero_fd < 0)
if (vm_init() < 0)
return 1;
page_size = getpagesize();
page = (char *)mmap(0, page_size, PROT_READ, MAP_PRIVATE, zero_fd, 0);
if (page == MAP_FAILED)
if ((page = (char *)vm_acquire(page_size)) == VM_MAP_FAILED)
return 1;
if (vm_protect((char *)page, page_size, VM_PAGE_READ) < 0)
return 1;
if (!sigsegv_install_handler(sigsegv_test_handler))
@ -284,6 +408,7 @@ int main(void)
if (handler_called != 1)
return 1;
vm_exit();
return 0;
}
#endif

View File

@ -28,21 +28,14 @@
* Page-aligned memory allocation
*/
// Align on page boundaries
static uintptr align_on_page_boundary(uintptr size)
// Extend size to page boundary
static uint32 page_extend(uint32 size)
{
const uint32 page_size = getpagesize();
const uint32 page_mask = page_size - 1;
return (size + page_mask) & ~page_mask;
}
// Allocate memory on page boundary
static void * allocate_framebuffer(uint32 size, uint8 * hint = 0)
{
// Remind that the system can allocate at 0x00000000...
return mmap((caddr_t)hint, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
}
// Screen fault handler
static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
{
@ -55,10 +48,10 @@ static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_addres
*/
if ((addr >= mainBuffer.memStart) && (addr < mainBuffer.memEnd)) {
const int page = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
caddr_t page_ad = (caddr_t)(addr & ~(mainBuffer.pageSize - 1));
caddr_t page_ad = (caddr_t)(addr & -mainBuffer.pageSize);
LOCK_VOSF;
PFLAG_SET(page);
mprotect(page_ad, mainBuffer.pageSize, PROT_READ | PROT_WRITE);
vm_protect((char *)page_ad, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
mainBuffer.dirty = true;
UNLOCK_VOSF;
return true;
@ -127,7 +120,7 @@ static inline void update_display_window_vosf(void)
// Make the dirty pages read-only again
const int32 offset = first_page << mainBuffer.pageBits;
const uint32 length = (page - first_page) << mainBuffer.pageBits;
mprotect((caddr_t)(mainBuffer.memStart + offset), length, PROT_READ);
vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ);
// There is at least one line to update
const int y1 = mainBuffer.pageInfo[first_page].top;
@ -185,7 +178,7 @@ static inline void update_display_dga_vosf(void)
// Make the dirty pages read-only again
const int32 offset = first_page << mainBuffer.pageBits;
const uint32 length = (page - first_page) << mainBuffer.pageBits;
mprotect((caddr_t)(mainBuffer.memStart + offset), length, PROT_READ);
vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ);
// I am sure that y2 >= y1 and depth != 1
const int y1 = mainBuffer.pageInfo[first_page].top;

View File

@ -56,6 +56,7 @@
# include <fcntl.h>
# include <sys/mman.h>
# include "sigsegv.h"
# include "vm_alloc.h"
#endif
#include "cpu_emulation.h"
@ -187,9 +188,9 @@ struct ScreenPageInfo {
};
struct ScreenInfo {
uint32 memBase; // Real start address
uint32 memStart; // Start address aligned to page boundary
uint32 memEnd; // Address of one-past-the-end of the screen
uintptr memBase; // Real start address
uintptr memStart; // Start address aligned to page boundary
uintptr memEnd; // Address of one-past-the-end of the screen
uint32 memLength; // Length of the memory addressed by the screen pages
uint32 pageSize; // Size of a page
@ -544,15 +545,11 @@ static bool init_window(int width, int height)
}
#ifdef ENABLE_VOSF
// Allocate a page-aligned chunk of memory for frame buffer
the_buffer_size = align_on_page_boundary((aligned_height + 2) * img->bytes_per_line);
// Allocate memory for frame buffer (SIZE is extended to page-boundary)
the_host_buffer = the_buffer_copy;
the_buffer_copy = (uint8 *)allocate_framebuffer(the_buffer_size);
memset(the_buffer_copy, 0, the_buffer_size);
the_buffer = (uint8 *)allocate_framebuffer(the_buffer_size);
memset(the_buffer, 0, the_buffer_size);
the_buffer_size = page_extend((aligned_height + 2) * img->bytes_per_line);
the_buffer_copy = (uint8 *)vm_acquire(the_buffer_size);
the_buffer = (uint8 *)vm_acquire(the_buffer_size);
#else
// Allocate memory for frame buffer
the_buffer = (uint8 *)malloc((aligned_height + 2) * img->bytes_per_line);
@ -721,12 +718,11 @@ static bool init_fbdev_dga(char *in_fb_name)
use_vosf = Screen_blitter_init(&visualInfo, true);
if (use_vosf) {
// Allocate memory for frame buffer (SIZE is extended to page-boundary)
the_host_buffer = the_buffer;
the_buffer_size = align_on_page_boundary((height + 2) * bytes_per_row);
the_buffer_copy = (uint8 *)malloc(the_buffer_size);
memset(the_buffer_copy, 0, the_buffer_size);
the_buffer = (uint8 *)allocate_framebuffer(the_buffer_size);
memset(the_buffer, 0, the_buffer_size);
the_buffer_size = page_extend((height + 2) * bytes_per_row);
the_buffer_copy = (uint8 *)vm_acquire(the_buffer_size);
the_buffer = (uint8 *)vm_acquire(the_buffer_size);
}
#else
use_vosf = false;
@ -822,22 +818,22 @@ static bool init_xf86_dga(int width, int height)
break;
}
#ifdef VIDEO_VOSF
#if REAL_ADDRESSING || DIRECT_ADDRESSING
// Screen_blitter_init() returns TRUE if VOSF is mandatory
// i.e. the framebuffer update function is not Blit_Copy_Raw
use_vosf = Screen_blitter_init(&visualInfo, true);
if (use_vosf) {
// Allocate memory for frame buffer (SIZE is extended to page-boundary)
the_host_buffer = the_buffer;
the_buffer_size = align_on_page_boundary((height + 2) * bytes_per_row);
the_buffer_copy = (uint8 *)malloc(the_buffer_size);
memset(the_buffer_copy, 0, the_buffer_size);
the_buffer = (uint8 *)allocate_framebuffer(the_buffer_size);
memset(the_buffer, 0, the_buffer_size);
the_buffer_size = page_extend((height + 2) * bytes_per_row);
the_buffer_copy = (uint8 *)vm_acquire(the_buffer_size);
the_buffer = (uint8 *)vm_acquire(the_buffer_size);
}
#elif defined(ENABLE_VOSF)
// The UAE memory handlers will already handle color conversion, if needed.
#else
use_vosf = false;
#endif
#endif
set_video_monitor(width, height, bytes_per_row, true);
@ -926,9 +922,9 @@ bool VideoInitBuffer()
const uint32 page_size = getpagesize();
const uint32 page_mask = page_size - 1;
mainBuffer.memBase = (uint32) the_buffer;
mainBuffer.memBase = (uintptr) the_buffer;
// Align the frame buffer on page boundary
mainBuffer.memStart = (uint32)((((unsigned long) the_buffer) + page_mask) & ~page_mask);
mainBuffer.memStart = (uintptr)((((unsigned long) the_buffer) + page_mask) & ~page_mask);
mainBuffer.memLength = the_buffer_size;
mainBuffer.memEnd = mainBuffer.memStart + mainBuffer.memLength;
@ -976,7 +972,7 @@ bool VideoInitBuffer()
}
// We can now write-protect the frame buffer
if (mprotect((caddr_t)mainBuffer.memStart, mainBuffer.memLength, PROT_READ) != 0)
if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
return false;
}
#endif
@ -1260,13 +1256,13 @@ void VideoExit(void)
}
#ifdef ENABLE_VOSF
else {
if (the_buffer != (uint8 *)MAP_FAILED) {
munmap((caddr_t)the_buffer, the_buffer_size);
if (the_buffer != (uint8 *)VM_MAP_FAILED) {
vm_release(the_buffer, the_buffer_size);
the_buffer = 0;
}
if (the_buffer_copy != (uint8 *)MAP_FAILED) {
munmap((caddr_t)the_buffer_copy, the_buffer_size);
if (the_buffer_copy != (uint8 *)VM_MAP_FAILED) {
vm_release(the_buffer_copy, the_buffer_size);
the_buffer_copy = 0;
}
}

View File

@ -0,0 +1,258 @@
/*
* vm_alloc.cpp - Wrapper to various virtual memory allocation schemes
* (supports mmap, vm_allocate or fallbacks to malloc)
*
* Basilisk II (C) 1997-2001 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// TODO: Win32 VMs ?
#include <stdlib.h>
#include <string.h>
#include "vm_alloc.h"
#ifdef HAVE_MACH_VM
#ifndef HAVE_MACH_TASK_SELF
#ifdef HAVE_TASK_SELF
#define mach_task_self task_self
#else
#error "No task_self(), you lose."
#endif
#endif
#endif
#ifdef HAVE_MMAP_VM
#ifdef HAVE_MMAP_ANON
#define map_flags (MAP_PRIVATE | MAP_ANON)
#define zero_fd -1
#else
#ifdef HAVE_MMAP_ANONYMOUS
#define map_flags (MAP_PRIVATE | MAP_ANONYMOUS)
#define zero_fd -1
#else
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#define map_flags (MAP_PRIVATE)
static int zero_fd = -1;
#endif
#endif
#endif
/* Initialize the VM system. Returns 0 if successful, -1 for errors. */
int vm_init(void)
{
#ifdef HAVE_MMAP_VM
#ifndef zero_fd
zero_fd = open("/dev/zero", O_RDWR);
if (zero_fd < 0)
return -1;
#endif
#endif
return 0;
}
/* Deallocate all internal data used to wrap virtual memory allocators. */
void vm_exit(void)
{
#ifdef HAVE_MMAP_VM
#ifndef zero_fd
close(zero_fd);
#endif
#endif
}
/* Allocate zero-filled memory of SIZE bytes. The mapping is private
and default protection bits are read / write. The return value
is the actual mapping address chosen or VM_MAP_FAILED for errors. */
void * vm_acquire(size_t size)
{
void * addr;
#ifdef HAVE_MACH_VM
// vm_allocate() returns a zero-filled memory region
if (vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, TRUE) != KERN_SUCCESS)
return VM_MAP_FAILED;
#else
#ifdef HAVE_MMAP_VM
if ((addr = mmap(0, size, VM_PAGE_DEFAULT, map_flags, zero_fd, 0)) == MAP_FAILED)
return VM_MAP_FAILED;
// Since I don't know the standard behavior of mmap(), zero-fill here
if (memset(addr, 0, size) != addr)
return VM_MAP_FAILED;
#else
if ((addr = calloc(size, 1)) == 0)
return VM_MAP_FAILED;
// Omit changes for protections because they are not supported in this mode
return addr;
#endif
#endif
// Explicitely protect the newly mapped region here because on some systems,
// say MacOS X, mmap() doesn't honour the requested protection flags.
if (vm_protect(addr, size, VM_PAGE_DEFAULT) != 0)
return VM_MAP_FAILED;
return addr;
}
/* Allocate zero-filled memory at exactly ADDR (which must be page-aligned).
Retuns 0 if successful, -1 on errors. */
int vm_acquire_fixed(void * addr, size_t size)
{
#ifdef HAVE_MACH_VM
// vm_allocate() returns a zero-filled memory region
if (vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, 0) != KERN_SUCCESS)
return -1;
#else
#ifdef HAVE_MMAP_VM
if (mmap(addr, size, VM_PAGE_DEFAULT, map_flags | MAP_FIXED, zero_fd, 0) == MAP_FAILED)
return -1;
// Since I don't know the standard behavior of mmap(), zero-fill here
if (memset(0, 0, size) != 0)
return -1;
#else
// Unsupported
return -1;
#endif
#endif
// Explicitely protect the newly mapped region here because on some systems,
// say MacOS X, mmap() doesn't honour the requested protection flags.
if (vm_protect(0, size, VM_PAGE_DEFAULT) != 0)
return -1;
return 0;
}
/* Deallocate any mapping for the region starting at ADDR and extending
LEN bytes. Returns 0 if successful, -1 on errors. */
int vm_release(void * addr, size_t size)
{
#ifdef HAVE_MACH_VM
int ret_code = vm_deallocate(mach_task_self(), (vm_address_t)addr, size);
return ret_code == KERN_SUCCESS ? 0 : -1;
#else
#ifdef HAVE_MMAP_VM
int ret_code = munmap(addr, size);
return ret_code == 0 ? 0 : -1;
#else
free(addr);
return 0;
#endif
#endif
}
/* Change the memory protection of the region starting at ADDR and
extending LEN bytes to PROT. Returns 0 if successful, -1 for errors. */
int vm_protect(void * addr, size_t size, int prot)
{
#ifdef HAVE_MACH_VM
int ret_code = vm_protect(mach_task_self(), (vm_address_t)addr, size, 0, prot);
return ret_code == KERN_SUCCESS ? 0 : -1;
#else
#ifdef HAVE_MMAP_VM
int ret_code = mprotect(addr, size, prot);
return ret_code == 0 ? 0 : -1;
#else
// Unsupported
return -1;
#endif
#endif
}
#ifdef CONFIGURE_TEST_VM_MAP
/* Tests covered here:
- TEST_VM_PROT_* program slices actually succeeds when a crash occurs
- TEST_VM_MAP_ANON* program slices succeeds when it could be compiled
*/
int main(void)
{
vm_init();
#define page_align(address) ((char *)((unsigned long)(address) & -page_size))
unsigned long page_size = getpagesize();
const int area_size = 6 * page_size;
volatile char * area = (volatile char *) vm_acquire(area_size);
volatile char * fault_address = area + (page_size * 7) / 2;
#if defined(TEST_VM_MMAP_ANON) || defined(TEST_VM_MMAP_ANONYMOUS)
if (area == VM_MAP_FAILED)
return 1;
if (vm_release((char *)area, area_size) < 0)
return 1;
return 0;
#endif
#if defined(TEST_VM_PROT_NONE_READ) || defined(TEST_VM_PROT_NONE_WRITE)
if (area == VM_MAP_FAILED)
return 0;
if (vm_protect(page_align(fault_address), page_size, VM_PAGE_NOACCESS) < 0)
return 0;
#endif
#if defined(TEST_VM_PROT_RDWR_WRITE)
if (area == VM_MAP_FAILED)
return 1;
if (vm_protect(page_align(fault_address), page_size, VM_PAGE_READ) < 0)
return 1;
if (vm_protect(page_align(fault_address), page_size, VM_PAGE_READ | VM_PAGE_WRITE) < 0)
return 1;
#endif
#if defined(TEST_VM_PROT_READ_WRITE)
if (vm_protect(page_align(fault_address), page_size, VM_PAGE_READ) < 0)
return 0;
#endif
#if defined(TEST_VM_PROT_NONE_READ)
// this should cause a core dump
char foo = *fault_address;
return 0;
#endif
#if defined(TEST_VM_PROT_NONE_WRITE) || defined(TEST_VM_PROT_READ_WRITE)
// this should cause a core dump
*fault_address = 'z';
return 0;
#endif
#if defined(TEST_VM_PROT_RDWR_WRITE)
// this should not cause a core dump
*fault_address = 'z';
return 0;
#endif
}
#endif

View File

@ -0,0 +1,96 @@
/*
* vm_alloc.h - Wrapper to various virtual memory allocation schemes
* (supports mmap, vm_allocate or fallbacks to malloc)
*
* Basilisk II (C) 1997-2001 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// TODO: Win32 VM ?
#ifndef VM_ALLOC_H
#define VM_ALLOC_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
/* Return value of `vm_acquire' in case of an error. */
#ifdef HAVE_MACH_VM
#define VM_MAP_FAILED ((void *)-1)
#else
#ifdef HAVE_MMAP_VM
#define VM_MAP_FAILED ((void *)-1)
#else
#define VM_MAP_FAILED 0
#endif
#endif
/* Protection bits. */
#ifdef HAVE_MACH_VM
#define VM_PAGE_NOACCESS VM_PROT_NONE
#define VM_PAGE_READ VM_PROT_READ
#define VM_PAGE_WRITE VM_PROT_WRITE
#define VM_PAGE_EXECUTE VM_PROT_EXECUTE
#else
#ifdef HAVE_MMAP_VM
#define VM_PAGE_NOACCESS PROT_NONE
#define VM_PAGE_READ PROT_READ
#define VM_PAGE_WRITE PROT_WRITE
#define VM_PAGE_EXECUTE PROT_EXEC
#else
#define VM_PAGE_NOACCESS 0x0
#define VM_PAGE_READ 0x1
#define VM_PAGE_WRITE 0x2
#define VM_PAGE_EXECUTE 0x4
#endif
#endif
/* Default protection bits. */
#define VM_PAGE_DEFAULT (VM_PAGE_READ | VM_PAGE_WRITE)
/* Initialize the VM system. Returns 0 if successful, -1 for errors. */
extern int vm_init(void);
/* Deallocate all internal data used to wrap virtual memory allocators. */
extern void vm_exit(void);
/* Allocate zero-filled memory of SIZE bytes. The mapping is private
and default protection bits are read / write. The return value
is the actual mapping address chosen or VM_MAP_FAILED for errors. */
extern void * vm_acquire(size_t size);
/* Allocate zero-filled memory at exactly ADDR (which must be page-aligned).
Returns 0 if successful, -1 on errors. */
extern int vm_acquire_fixed(void * addr, size_t size);
/* Deallocate any mapping for the region starting at ADDR and extending
LEN bytes. Returns 0 if successful, -1 on errors. */
extern int vm_release(void * addr, size_t size);
/* Change the memory protection of the region starting at ADDR and
extending LEN bytes to PROT. Returns 0 if successful, -1 for errors. */
extern int vm_protect(void * addr, size_t size, int prot);
#endif /* VM_ALLOC_H */

View File

@ -64,7 +64,10 @@ bool Init680x0(void)
RAMBaseMac = (uint32)RAMBaseHost;
ROMBaseMac = (uint32)ROMBaseHost;
#elif DIRECT_ADDRESSING
InitMEMBaseDiff(RAMBaseHost, RAMBaseMac);
// Mac address space = host address space minus constant offset (MEMBaseDiff)
// NOTE: MEMBaseDiff is set in main_unix.cpp/main()
RAMBaseMac = 0;
ROMBaseMac = Host2MacAddr(ROMBaseHost);
#else
// Initialize UAE memory banks
RAMBaseMac = 0;

View File

@ -113,16 +113,15 @@ extern void byteput(uaecptr addr, uae_u32 b);
#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */
#if REAL_ADDRESSING
const uintptr MEMBaseDiff = 0;
#define do_get_real_address(a) ((uae_u8 *)(a))
#define do_get_virtual_address(a) ((uae_u32)(a))
#define InitMEMBaseDiff(va, ra) do { } while (0)
#endif /* REAL_ADDRESSING */
#if DIRECT_ADDRESSING
extern uintptr MEMBaseDiff;
#define do_get_real_address(a) ((uae_u8 *)(a) + MEMBaseDiff)
#define do_get_virtual_address(a) ((uae_u32)(a) - MEMBaseDiff)
#define InitMEMBaseDiff(va, ra) (MEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
#endif /* DIRECT_ADDRESSING */
#if REAL_ADDRESSING || DIRECT_ADDRESSING