--- SheepShaver/src/Unix/main_unix.cpp 2002/02/21 15:12:12 1.2 +++ SheepShaver/src/Unix/main_unix.cpp 2003/12/05 12:41:19 1.19 @@ -107,6 +107,9 @@ #include "macos_util.h" #include "rom_patches.h" #include "user_strings.h" +#include "vm_alloc.h" +#include "sigsegv.h" +#include "thunks.h" #define DEBUG 0 #include "debug.h" @@ -143,29 +146,10 @@ const char ROM_FILE_NAME[] = "ROM"; const char ROM_FILE_NAME2[] = "Mac OS ROM"; -const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area -const uint32 ROM_END = ROM_BASE + ROM_SIZE; // End of ROM - -const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data -const uint32 KERNEL_DATA2_BASE = 0x5fffe000; // Alternate address of Kernel Data -const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area - +const uintptr RAM_BASE = 0x20000000; // Base address of RAM const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack -// 68k Emulator Data -struct EmulatorData { - uint32 v[0x400]; -}; - - -// Kernel Data -struct KernelData { - uint32 v[0x400]; - EmulatorData ed; -}; - - #if !EMULATED_PPC // Structure in which registers are saved in a signal handler; // sigcontext->regs points to it @@ -197,7 +181,7 @@ int64 BusClockSpeed; // Bus clock speed // Global variables -static char *x_display_name = NULL; // X11 display name +char *x_display_name = NULL; // X11 display name Display *x_display = NULL; // X11 display handle static int zero_fd = 0; // FD of /dev/zero @@ -205,7 +189,6 @@ static bool lm_area_mapped = false; // static int kernel_area = -1; // SHM ID of Kernel Data area static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped -static void *mmap_RAMBase = NULL; // Base address of mmap()ed RAM area static KernelData *kernel_data; // Pointer to Kernel Data static EmulatorData *emulator_data; @@ -220,8 +203,8 @@ static pthread_t emul_thread; // MacO static bool ready_for_signals = false; // Handler installed, signals can be sent static int64 num_segv = 0; // Number of handled SEGV signals -#if !EMULATED_PPC static struct sigaction sigusr2_action; // Interrupt signal (of emulator thread) +#if !EMULATED_PPC static struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) static struct sigaction sigill_action; // Illegal instruction signal (of emulator thread) static void *sig_stack = NULL; // Stack for signal handlers @@ -230,13 +213,22 @@ static bool emul_thread_fatal = false; static sigregs sigsegv_regs; // Register dump when crashed #endif +uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros +uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data +uintptr SheepMem::top = 0; // Top of SheepShaver data (stack like storage) + // Prototypes static void Quit(void); static void *emul_func(void *arg); static void *nvram_func(void *arg); static void *tick_func(void *arg); -#if !EMULATED_PPC +#if EMULATED_PPC +static void sigusr2_handler(int sig); +extern void emul_ppc(uint32 start); +extern void init_emul_ppc(void); +extern void exit_emul_ppc(void); +#else static void sigusr2_handler(int sig, sigcontext_struct *sc); static void sigsegv_handler(int sig, sigcontext_struct *sc); static void sigill_handler(int sig, sigcontext_struct *sc); @@ -244,11 +236,7 @@ static void sigill_handler(int sig, sigc // From asm_linux.S -#if EMULATED_PPC -extern int atomic_add(int *var, int v); -extern int atomic_and(int *var, int v); -extern int atomic_or(int *var, int v); -#else +#if !EMULATED_PPC extern "C" void *get_toc(void); extern "C" void *get_sp(void); extern "C" void flush_icache_range(void *start, void *end); @@ -263,49 +251,46 @@ extern void paranoia_check(void); #endif -// Decode LZSS data -static void decode_lzss(const uint8 *src, uint8 *dest, int size) +#if EMULATED_PPC +/* + * Atomic operations + */ + +#if HAVE_SPINLOCKS +static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED; +#else +#define spin_lock(LOCK) +#define spin_unlock(LOCK) +#endif + +int atomic_add(int *var, int v) { - char dict[0x1000]; - int run_mask = 0, dict_idx = 0xfee; - for (;;) { - if (run_mask < 0x100) { - // Start new run - if (--size < 0) - break; - run_mask = *src++ | 0xff00; - } - bool bit = run_mask & 1; - run_mask >>= 1; - if (bit) { - // Verbatim copy - if (--size < 0) - break; - int c = *src++; - dict[dict_idx++] = c; - *dest++ = c; - dict_idx &= 0xfff; - } else { - // Copy from dictionary - if (--size < 0) - break; - int idx = *src++; - if (--size < 0) - break; - int cnt = *src++; - idx |= (cnt << 4) & 0xf00; - cnt = (cnt & 0x0f) + 3; - while (cnt--) { - char c = dict[idx++]; - dict[dict_idx++] = c; - *dest++ = c; - idx &= 0xfff; - dict_idx &= 0xfff; - } - } - } + spin_lock(&atomic_ops_lock); + int ret = *var; + *var += v; + spin_unlock(&atomic_ops_lock); + return ret; } +int atomic_and(int *var, int v) +{ + spin_lock(&atomic_ops_lock); + int ret = *var; + *var &= v; + spin_unlock(&atomic_ops_lock); + return ret; +} + +int atomic_or(int *var, int v) +{ + spin_lock(&atomic_ops_lock); + int ret = *var; + *var |= v; + spin_unlock(&atomic_ops_lock); + return ret; +} +#endif + /* * Main program @@ -325,7 +310,6 @@ int main(int argc, char **argv) char str[256]; uint32 *boot_globs; int16 i16; - int drive, driver; int rom_fd; FILE *proc_file; const char *rom_path; @@ -335,7 +319,6 @@ int main(int argc, char **argv) // Initialize variables RAMBase = 0; - mmap_RAMBase = NULL; tzset(); // Print some info @@ -464,7 +447,7 @@ int main(int argc, char **argv) } // Create Low Memory area (0x0000..0x3000) - if (mmap((char *)0x0000, 0x3000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) { + if (vm_acquire_fixed((char *)0, 0x3000) < 0) { sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; @@ -488,17 +471,31 @@ int main(int argc, char **argv) ErrorAlert(str); goto quit; } - kernel_data = (KernelData *)0x68ffe000; + kernel_data = (KernelData *)KERNEL_DATA_BASE; emulator_data = &kernel_data->ed; - KernelDataAddr = (uint32)kernel_data; + KernelDataAddr = KERNEL_DATA_BASE; D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data)); + // Create area for SheepShaver data + if (!SheepMem::Init()) { + sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno)); + ErrorAlert(str); + goto quit; + } + // Create area for Mac ROM - if (mmap((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) { + if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) { + sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); + ErrorAlert(str); + goto quit; + } +#if !EMULATED_PPC || defined(__powerpc__) + if (vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } +#endif rom_area_mapped = true; D(bug("ROM area at %08x\n", ROM_BASE)); @@ -509,13 +506,19 @@ int main(int argc, char **argv) RAMSize = 8*1024*1024; } - mmap_RAMBase = mmap((void *)0x20000000, RAMSize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0); - if (mmap_RAMBase == (void *)-1) { + if (vm_acquire_fixed((char *)RAM_BASE, RAMSize) < 0) { + sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); + ErrorAlert(str); + goto quit; + } +#if !EMULATED_PPC + if (vm_protect((char *)RAM_BASE, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } - RAMBase = (uint32)mmap_RAMBase; +#endif + RAMBase = RAM_BASE; ram_area_mapped = true; D(bug("RAM area at %08x\n", RAMBase)); @@ -540,43 +543,10 @@ int main(int argc, char **argv) rom_tmp = new uint8[ROM_SIZE]; actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE); close(rom_fd); - if (actual == ROM_SIZE) { - // Plain ROM image - memcpy((void *)ROM_BASE, rom_tmp, ROM_SIZE); - delete[] rom_tmp; - } else { - if (strncmp((char *)rom_tmp, "", 11) == 0) { - // CHRP compressed ROM image - D(bug("CHRP ROM image\n")); - uint32 lzss_offset, lzss_size; - - char *s = strstr((char *)rom_tmp, "constant lzss-offset"); - if (s == NULL) { - ErrorAlert(GetString(STR_ROM_SIZE_ERR)); - goto quit; - } - s -= 7; - if (sscanf(s, "%06x", &lzss_offset) != 1) { - ErrorAlert(GetString(STR_ROM_SIZE_ERR)); - goto quit; - } - s = strstr((char *)rom_tmp, "constant lzss-size"); - if (s == NULL) { - ErrorAlert(GetString(STR_ROM_SIZE_ERR)); - goto quit; - } - s -= 7; - if (sscanf(s, "%06x", &lzss_size) != 1) { - ErrorAlert(GetString(STR_ROM_SIZE_ERR)); - goto quit; - } - D(bug("Offset of compressed data: %08x\n", lzss_offset)); - D(bug("Size of compressed data: %08x\n", lzss_size)); - - D(bug("Uncompressing ROM...\n")); - decode_lzss(rom_tmp + lzss_offset, (uint8 *)ROM_BASE, lzss_size); - delete[] rom_tmp; - } else if (rom_size != 4*1024*1024) { + + // Decode Mac ROM + if (!DecodeROM(rom_tmp, actual)) { + if (rom_size != 4*1024*1024) { ErrorAlert(GetString(STR_ROM_SIZE_ERR)); goto quit; } else { @@ -584,15 +554,16 @@ int main(int argc, char **argv) goto quit; } } + delete[] rom_tmp; // Load NVRAM XPRAMInit(); // Set boot volume - drive = PrefsFindInt32("bootdrive"); + i16 = PrefsFindInt32("bootdrive"); XPRAM[0x1378] = i16 >> 8; XPRAM[0x1379] = i16 & 0xff; - driver = PrefsFindInt32("bootdriver"); + i16 = PrefsFindInt32("bootdriver"); XPRAM[0x137a] = i16 >> 8; XPRAM[0x137b] = i16 & 0xff; @@ -605,6 +576,10 @@ int main(int argc, char **argv) boot_globs[1] = htonl(RAMSize); boot_globs[2] = htonl((uint32)-1); // End of bank table + // Init thunks + if (!ThunksInit()) + goto quit; + // Init drivers SonyInit(); DiskInit(); @@ -643,21 +618,22 @@ int main(int argc, char **argv) #if !EMULATED_PPC MakeExecutable(0, (void *)ROM_BASE, ROM_AREA_SIZE); #endif - mprotect((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ); + vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE); // Initialize Kernel Data memset(kernel_data, 0, sizeof(KernelData)); if (ROMType == ROMTYPE_NEWWORLD) { - static uint32 of_dev_tree[4] = {0, 0, 0, 0}; - static uint8 vector_lookup_tbl[128]; - static uint8 vector_mask_tbl[64]; + uintptr of_dev_tree = SheepMem::Reserve(4 * sizeof(uint32)); + memset((void *)of_dev_tree, 0, 4 * sizeof(uint32)); + uintptr vector_lookup_tbl = SheepMem::Reserve(128); + uintptr vector_mask_tbl = SheepMem::Reserve(64); memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80); - memset(vector_lookup_tbl, 0, 128); - memset(vector_mask_tbl, 0, 64); + memset((void *)vector_lookup_tbl, 0, 128); + memset((void *)vector_mask_tbl, 0, 64); kernel_data->v[0xb80 >> 2] = htonl(ROM_BASE); - kernel_data->v[0xb84 >> 2] = htonl((uint32)of_dev_tree); // OF device tree base - kernel_data->v[0xb90 >> 2] = htonl((uint32)vector_lookup_tbl); - kernel_data->v[0xb94 >> 2] = htonl((uint32)vector_mask_tbl); + kernel_data->v[0xb84 >> 2] = htonl(of_dev_tree); // OF device tree base + kernel_data->v[0xb90 >> 2] = htonl(vector_lookup_tbl); + kernel_data->v[0xb94 >> 2] = htonl(vector_mask_tbl); kernel_data->v[0xb98 >> 2] = htonl(ROM_BASE); // OpenPIC base kernel_data->v[0xbb0 >> 2] = htonl(0); // ADB base kernel_data->v[0xc20 >> 2] = htonl(RAMSize); @@ -693,20 +669,21 @@ int main(int argc, char **argv) D(bug("Initializing Low Memory...\n")); memset(NULL, 0, 0x3000); WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h')); // Signature to detect SheepShaver - WriteMacInt32(XLM_KERNEL_DATA, (uint32)kernel_data); // For trap replacement routines + WriteMacInt32(XLM_KERNEL_DATA, KernelDataAddr); // For trap replacement routines WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode) + WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0 #if !EMULATED_PPC - WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator - WriteMacInt32(XLM_ETHER_INIT, (uint32)InitStreamModule); // DLPI ethernet driver functions - WriteMacInt32(XLM_ETHER_TERM, (uint32)TerminateStreamModule); - WriteMacInt32(XLM_ETHER_OPEN, (uint32)ether_open); - WriteMacInt32(XLM_ETHER_CLOSE, (uint32)ether_close); - WriteMacInt32(XLM_ETHER_WPUT, (uint32)ether_wput); - WriteMacInt32(XLM_ETHER_RSRV, (uint32)ether_rsrv); - WriteMacInt32(XLM_VIDEO_DOIO, (uint32)VideoDoDriverIO); + WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator #endif + WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT)); // DLPI ethernet driver functions + WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM)); + WriteMacInt32(XLM_ETHER_OPEN, NativeFunction(NATIVE_ETHER_OPEN)); + WriteMacInt32(XLM_ETHER_CLOSE, NativeFunction(NATIVE_ETHER_CLOSE)); + WriteMacInt32(XLM_ETHER_WPUT, NativeFunction(NATIVE_ETHER_WPUT)); + WriteMacInt32(XLM_ETHER_RSRV, NativeFunction(NATIVE_ETHER_RSRV)); + WriteMacInt32(XLM_VIDEO_DOIO, NativeFunction(NATIVE_VIDEO_DO_DRIVER_IO)); D(bug("Low Memory initialized\n")); // Start 60Hz thread @@ -767,18 +744,21 @@ int main(int argc, char **argv) ErrorAlert(str); goto quit; } +#endif // Install interrupt signal handler sigemptyset(&sigusr2_action.sa_mask); sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler; + sigusr2_action.sa_flags = 0; +#if !EMULATED_PPC sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART; +#endif sigusr2_action.sa_restorer = NULL; if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) { sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno)); ErrorAlert(str); goto quit; } -#endif // Get my thread ID and execute MacOS thread function emul_thread = pthread_self(); @@ -797,6 +777,11 @@ quit: static void Quit(void) { +#if EMULATED_PPC + // Exit PowerPC emulation + exit_emul_ppc(); +#endif + // Stop 60Hz thread if (tick_thread_active) { pthread_cancel(tick_thread); @@ -853,13 +838,16 @@ static void Quit(void) DiskExit(); SonyExit(); + // Delete SheepShaver globals + SheepMem::Exit(); + // Delete RAM area if (ram_area_mapped) - munmap(mmap_RAMBase, RAMSize); + vm_release((char *)RAM_BASE, RAMSize); // Delete ROM area if (rom_area_mapped) - munmap((char *)ROM_BASE, ROM_AREA_SIZE); + vm_release((char *)ROM_BASE, ROM_AREA_SIZE); // Delete Kernel Data area if (kernel_area >= 0) { @@ -900,8 +888,6 @@ static void Quit(void) */ #if EMULATED_PPC -extern void emul_ppc(uint32 start); -extern void init_emul_ppc(void); void jump_to_rom(uint32 entry) { init_emul_ppc(); @@ -970,19 +956,6 @@ void Execute68kTrap(uint16 trap, M68kReg /* - * Execute PPC code from EMUL_OP routine (real mode switch) - */ - -void ExecutePPC(void (*func)()) -{ - uint32 tvect[2] = {(uint32)func, 0}; // Fake TVECT - RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, tvect); - M68kRegisters r; - Execute68k((uint32)&desc, &r); -} - - -/* * Quit emulator (cause return from jump_to_rom) */ @@ -1041,10 +1014,12 @@ void Dump68kRegs(M68kRegisters *r) void MakeExecutable(int dummy, void *start, uint32 length) { -#if !EMULATED_PPC - if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE))) + if (((uintptr)start >= ROM_BASE) && ((uintptr)start < (ROM_BASE + ROM_SIZE))) return; - flush_icache_range(start, (void *)((uint32)start + length)); +#if EMULATED_PPC + FlushCodeCache((uintptr)start, (uintptr)start + length); +#else + flush_icache_range(start, (void *)((uintptr)start + length)); #endif } @@ -1055,7 +1030,7 @@ void MakeExecutable(int dummy, void *sta void PatchAfterStartup(void) { - ExecutePPC(VideoInstallAccel); + ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL); InstallExtFS(); } @@ -1158,7 +1133,30 @@ static void *tick_func(void *arg) void Set_pthread_attr(pthread_attr_t *attr, int priority) { - // nothing to do +#ifdef HAVE_PTHREADS + pthread_attr_init(attr); +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) + // Some of these only work for superuser + if (geteuid() == 0) { + pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedpolicy(attr, SCHED_FIFO); + struct sched_param fifo_param; + fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) + + sched_get_priority_max(SCHED_FIFO)) / 2 + + priority); + pthread_attr_setschedparam(attr, &fifo_param); + } + if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) { +#ifdef PTHREAD_SCOPE_BOUND_NP + // If system scope is not available (eg. we're not running + // with CAP_SCHED_MGT capability on an SGI box), try bound + // scope. It exposes pthread scheduling to the kernel, + // without setting realtime priority. + pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP); +#endif + } +#endif +#endif } @@ -1166,6 +1164,56 @@ void Set_pthread_attr(pthread_attr_t *at * Mutexes */ +#ifdef HAVE_PTHREADS + +struct B2_mutex { + B2_mutex() { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + // Initialize the mutex for priority inheritance -- + // required for accurate timing. +#ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL + pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); +#endif +#if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL) + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); +#endif +#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); +#endif + pthread_mutex_init(&m, &attr); + pthread_mutexattr_destroy(&attr); + } + ~B2_mutex() { + pthread_mutex_trylock(&m); // Make sure it's locked before + pthread_mutex_unlock(&m); // unlocking it. + pthread_mutex_destroy(&m); + } + pthread_mutex_t m; +}; + +B2_mutex *B2_create_mutex(void) +{ + return new B2_mutex; +} + +void B2_lock_mutex(B2_mutex *mutex) +{ + pthread_mutex_lock(&mutex->m); +} + +void B2_unlock_mutex(B2_mutex *mutex) +{ + pthread_mutex_unlock(&mutex->m); +} + +void B2_delete_mutex(B2_mutex *mutex) +{ + delete mutex; +} + +#else + struct B2_mutex { int dummy; }; @@ -1188,24 +1236,20 @@ void B2_delete_mutex(B2_mutex *mutex) delete mutex; } +#endif + /* * Trigger signal USR2 from another thread */ +#if !EMULATED_PPC || ASYNC_IRQ void TriggerInterrupt(void) { -#if EMULATED_PPC - WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); -#else -#if 0 - WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); -#else if (ready_for_signals) pthread_kill(emul_thread, SIGUSR2); -#endif -#endif } +#endif /* @@ -1245,11 +1289,19 @@ void EnableInterrupt(void) } -#if !EMULATED_PPC /* * USR2 handler */ +#if EMULATED_PPC +static void sigusr2_handler(int sig) +{ +#if ASYNC_IRQ + extern void HandleInterrupt(void); + HandleInterrupt(); +#endif +} +#else static void sigusr2_handler(int sig, sigcontext_struct *sc) { pt_regs *r = sc->regs; @@ -1319,7 +1371,7 @@ static void sigusr2_handler(int sig, sig if (InterruptFlags & INTFLAG_VIA) { ClearInterruptFlag(INTFLAG_VIA); ADBInterrupt(); - ExecutePPC(VideoVBL); + ExecuteNative(NATIVE_VIDEO_VBL); } } #endif @@ -1331,33 +1383,36 @@ static void sigusr2_handler(int sig, sig } break; #endif - } } +#endif /* * SIGSEGV handler */ +#if !EMULATED_PPC static void sigsegv_handler(int sig, sigcontext_struct *sc) { pt_regs *r = sc->regs; + + // Get effective address + uint32 addr = r->dar; + +#if ENABLE_VOSF + // Handle screen fault. + extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction); + if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->nip)) + return; +#endif + num_segv++; // Fault in Mac ROM or RAM? bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize)); if (mac_fault) { - // Get opcode and divide into fields - uint32 opcode = *((uint32 *)r->nip); - uint32 primop = opcode >> 26; - uint32 exop = (opcode >> 1) & 0x3ff; - uint32 ra = (opcode >> 16) & 0x1f; - uint32 rb = (opcode >> 11) & 0x1f; - uint32 rd = (opcode >> 21) & 0x1f; - int32 imm = (int16)(opcode & 0xffff); - // "VM settings" during MacOS 8 installation if (r->nip == ROM_BASE + 0x488160 && r->gpr[20] == 0xf8000000) { r->nip += 4; @@ -1385,6 +1440,15 @@ static void sigsegv_handler(int sig, sig return; } + // Get opcode and divide into fields + uint32 opcode = *((uint32 *)r->nip); + uint32 primop = opcode >> 26; + uint32 exop = (opcode >> 1) & 0x3ff; + uint32 ra = (opcode >> 16) & 0x1f; + uint32 rb = (opcode >> 11) & 0x1f; + uint32 rd = (opcode >> 21) & 0x1f; + int32 imm = (int16)(opcode & 0xffff); + // Analyze opcode enum { TYPE_UNKNOWN, @@ -1468,27 +1532,6 @@ static void sigsegv_handler(int sig, sig transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break; } - // Calculate effective address - uint32 addr = 0; - switch (addr_mode) { - case MODE_X: - case MODE_UX: - if (ra == 0) - addr = r->gpr[rb]; - else - addr = r->gpr[ra] + r->gpr[rb]; - break; - case MODE_NORM: - case MODE_U: - if (ra == 0) - addr = (int32)(int16)imm; - else - addr = r->gpr[ra] + (int32)(int16)imm; - break; - default: - break; - } - // Ignore ROM writes if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) { // D(bug("WARNING: %s write access to ROM at %08lx, pc %08lx\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->nip)); @@ -1725,6 +1768,37 @@ rti:; /* + * Helpers to share 32-bit addressable data with MacOS + */ + +bool SheepMem::Init(void) +{ + if (vm_acquire_fixed((char *)base, size) < 0) + return false; + + zero_page = base + size; + + int page_size = getpagesize(); + if (vm_acquire_fixed((char *)zero_page, page_size) < 0) + return false; + memset((char *)zero_page, 0, page_size); + if (vm_protect((char *)zero_page, page_size, VM_PAGE_READ) < 0) + return false; + + top = base + size; + return true; +} + +void SheepMem::Exit(void) +{ + if (top) { + // The zero page is next to SheepShaver globals + vm_release((void *)base, size + getpagesize()); + } +} + + +/* * Display alert */