ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/main_unix.cpp
Revision: 1.1.1.1 (vendor branch)
Committed: 2002-02-04T16:58:13Z (22 years, 9 months ago) by cebix
Branch: cebix
CVS Tags: start
Changes since 1.1: +0 -0 lines
Log Message:
Imported sources

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * main_unix.cpp - Emulation core, Unix implementation
3     *
4     * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     /*
22     * NOTES:
23     *
24     * See main_beos.cpp for a description of the three operating modes.
25     *
26     * In addition to that, we have to handle the fact that the MacOS ABI
27     * is slightly different from the SysV ABI used by Linux:
28     * - Stack frames are different (e.g. LR is stored in 8(r1) under
29     * MacOS, but in 4(r1) under Linux)
30     * - There is no TOC under Linux; r2 is free for the user
31     * - r13 is used as a small data pointer under Linux (but appearently
32     * it is not used this way? To be sure, we specify -msdata=none
33     * in the Makefile)
34     * - As there is no TOC, there are also no TVECTs under Linux;
35     * function pointers point directly to the function code
36     * The Execute*() functions have to account for this. Additionally, we
37     * cannot simply call MacOS functions by getting their TVECT and jumping
38     * to it. Such calls are done via the call_macos*() functions in
39     * asm_linux.S that create a MacOS stack frame, load the TOC pointer
40     * and put the arguments into the right registers.
41     *
42     * As on the BeOS, we have to specify an alternate signal stack because
43     * interrupts (and, under Linux, Low Memory accesses) may occur when r1
44     * is pointing to the Kernel Data or to Low Memory. There is one
45     * problem, however, due to the alternate signal stack being global to
46     * all signal handlers. Consider the following scenario:
47     * - The main thread is executing some native PPC MacOS code in
48     * MODE_NATIVE, running on the MacOS stack (somewhere in the Mac RAM).
49     * - A SIGUSR2 interrupt occurs. The kernel switches to the signal
50     * stack and starts executing the SIGUSR2 signal handler.
51     * - The signal handler sees the MODE_NATIVE and calls ppc_interrupt()
52     * to handle a native interrupt.
53     * - ppc_interrupt() sets r1 to point to the Kernel Data and jumps to
54     * the nanokernel.
55     * - The nanokernel accesses a Low Memory global (most likely one of
56     * the XLMs), a SIGSEGV occurs.
57     * - The kernel sees that r1 does not point to the signal stack and
58     * switches to the signal stack again, thus overwriting the data that
59     * the SIGUSR2 handler put there.
60     * The same problem arises when calling ExecutePPC() inside the MODE_EMUL_OP
61     * interrupt handler.
62     *
63     * The solution is to set the signal stack to a second, "extra" stack
64     * inside the SIGUSR2 handler before entering the Nanokernel or calling
65     * ExecutePPC (or any function that might cause a mode switch). The signal
66     * stack is restored before exiting the SIGUSR2 handler.
67     *
68     * TODO:
69     * check if SIGSEGV handler works for all registers (including FP!)
70     */
71    
72     #include <unistd.h>
73     #include <fcntl.h>
74     #include <time.h>
75     #include <errno.h>
76     #include <stdio.h>
77     #include <stdlib.h>
78     #include <string.h>
79     #include <pthread.h>
80     #include <sys/mman.h>
81     #include <sys/ipc.h>
82     #include <sys/shm.h>
83     #include <signal.h>
84    
85     #include "sysdeps.h"
86     #include "main.h"
87     #include "version.h"
88     #include "prefs.h"
89     #include "prefs_editor.h"
90     #include "cpu_emulation.h"
91     #include "emul_op.h"
92     #include "xlowmem.h"
93     #include "xpram.h"
94     #include "timer.h"
95     #include "adb.h"
96     #include "sony.h"
97     #include "disk.h"
98     #include "cdrom.h"
99     #include "scsi.h"
100     #include "video.h"
101     #include "audio.h"
102     #include "ether.h"
103     #include "serial.h"
104     #include "clip.h"
105     #include "extfs.h"
106     #include "sys.h"
107     #include "macos_util.h"
108     #include "rom_patches.h"
109     #include "user_strings.h"
110    
111     #define DEBUG 0
112     #include "debug.h"
113    
114    
115     #include <X11/Xlib.h>
116    
117     #ifdef ENABLE_GTK
118     #include <gtk/gtk.h>
119     #endif
120    
121     #ifdef ENABLE_XF86_DGA
122     #include <X11/Xlib.h>
123     #include <X11/Xutil.h>
124     #include <X11/extensions/xf86dga.h>
125     #endif
126    
127     #ifdef ENABLE_MON
128     #include "mon.h"
129     #endif
130    
131    
132     // Enable Execute68k() safety checks?
133     #define SAFE_EXEC_68K 0
134    
135     // Interrupts in EMUL_OP mode?
136     #define INTERRUPTS_IN_EMUL_OP_MODE 1
137    
138     // Interrupts in native mode?
139     #define INTERRUPTS_IN_NATIVE_MODE 1
140    
141    
142     // Constants
143     const char ROM_FILE_NAME[] = "ROM";
144     const char ROM_FILE_NAME2[] = "Mac OS ROM";
145    
146     const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area
147     const uint32 ROM_END = ROM_BASE + ROM_SIZE; // End of ROM
148    
149     const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data
150     const uint32 KERNEL_DATA2_BASE = 0x5fffe000; // Alternate address of Kernel Data
151     const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area
152    
153     const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
154    
155    
156     // 68k Emulator Data
157     struct EmulatorData {
158     uint32 v[0x400];
159     };
160    
161    
162     // Kernel Data
163     struct KernelData {
164     uint32 v[0x400];
165     EmulatorData ed;
166     };
167    
168    
169     #if !EMULATED_PPC
170     // Structure in which registers are saved in a signal handler;
171     // sigcontext->regs points to it
172     // (see arch/ppc/kernel/signal.c)
173     typedef struct {
174     uint32 u[4];
175     } __attribute((aligned(16))) vector128;
176     #include <linux/elf.h>
177    
178     struct sigregs {
179     elf_gregset_t gp_regs; // Identical to pt_regs
180     double fp_regs[ELF_NFPREG]; // f0..f31 and fpsrc
181     //more (uninteresting) stuff following here
182     };
183     #endif
184    
185    
186     // Global variables (exported)
187     #if !EMULATED_PPC
188     void *TOC; // Small data pointer (r13)
189     #endif
190     uint32 RAMBase; // Base address of Mac RAM
191     uint32 RAMSize; // Size of Mac RAM
192     uint32 KernelDataAddr; // Address of Kernel Data
193     uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
194     uint32 PVR; // Theoretical PVR
195     int64 CPUClockSpeed; // Processor clock speed (Hz)
196     int64 BusClockSpeed; // Bus clock speed (Hz)
197    
198    
199     // Global variables
200     static char *x_display_name = NULL; // X11 display name
201     Display *x_display = NULL; // X11 display handle
202    
203     static int zero_fd = 0; // FD of /dev/zero
204     static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped
205     static int kernel_area = -1; // SHM ID of Kernel Data area
206     static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped
207     static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped
208     static void *mmap_RAMBase = NULL; // Base address of mmap()ed RAM area
209     static KernelData *kernel_data; // Pointer to Kernel Data
210     static EmulatorData *emulator_data;
211    
212     static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
213    
214     static bool nvram_thread_active = false; // Flag: NVRAM watchdog installed
215     static pthread_t nvram_thread; // NVRAM watchdog
216     static bool tick_thread_active = false; // Flag: MacOS thread installed
217     static pthread_t tick_thread; // 60Hz thread
218     static pthread_t emul_thread; // MacOS thread
219    
220     static bool ready_for_signals = false; // Handler installed, signals can be sent
221     static int64 num_segv = 0; // Number of handled SEGV signals
222    
223     #if !EMULATED_PPC
224     static struct sigaction sigusr2_action; // Interrupt signal (of emulator thread)
225     static struct sigaction sigsegv_action; // Data access exception signal (of emulator thread)
226     static struct sigaction sigill_action; // Illegal instruction signal (of emulator thread)
227     static void *sig_stack = NULL; // Stack for signal handlers
228     static void *extra_stack = NULL; // Stack for SIGSEGV inside interrupt handler
229     static bool emul_thread_fatal = false; // Flag: MacOS thread crashed, tick thread shall dump debug output
230     static sigregs sigsegv_regs; // Register dump when crashed
231     #endif
232    
233    
234     // Prototypes
235     static void Quit(void);
236     static void *emul_func(void *arg);
237     static void *nvram_func(void *arg);
238     static void *tick_func(void *arg);
239     #if !EMULATED_PPC
240     static void sigusr2_handler(int sig, sigcontext_struct *sc);
241     static void sigsegv_handler(int sig, sigcontext_struct *sc);
242     static void sigill_handler(int sig, sigcontext_struct *sc);
243     #endif
244    
245    
246     // From asm_linux.S
247     #if EMULATED_PPC
248     extern int atomic_add(int *var, int v);
249     extern int atomic_and(int *var, int v);
250     extern int atomic_or(int *var, int v);
251     #else
252     extern "C" void *get_toc(void);
253     extern "C" void *get_sp(void);
254     extern "C" void flush_icache_range(void *start, void *end);
255     extern "C" void jump_to_rom(uint32 entry, uint32 context);
256     extern "C" void quit_emulator(void);
257     extern "C" void execute_68k(uint32 pc, M68kRegisters *r);
258     extern "C" void ppc_interrupt(uint32 entry, uint32 kernel_data);
259     extern "C" int atomic_add(int *var, int v);
260     extern "C" int atomic_and(int *var, int v);
261     extern "C" int atomic_or(int *var, int v);
262     extern void paranoia_check(void);
263     #endif
264    
265    
266     // Decode LZSS data
267     static void decode_lzss(const uint8 *src, uint8 *dest, int size)
268     {
269     char dict[0x1000];
270     int run_mask = 0, dict_idx = 0xfee;
271     for (;;) {
272     if (run_mask < 0x100) {
273     // Start new run
274     if (--size < 0)
275     break;
276     run_mask = *src++ | 0xff00;
277     }
278     bool bit = run_mask & 1;
279     run_mask >>= 1;
280     if (bit) {
281     // Verbatim copy
282     if (--size < 0)
283     break;
284     int c = *src++;
285     dict[dict_idx++] = c;
286     *dest++ = c;
287     dict_idx &= 0xfff;
288     } else {
289     // Copy from dictionary
290     if (--size < 0)
291     break;
292     int idx = *src++;
293     if (--size < 0)
294     break;
295     int cnt = *src++;
296     idx |= (cnt << 4) & 0xf00;
297     cnt = (cnt & 0x0f) + 3;
298     while (cnt--) {
299     char c = dict[idx++];
300     dict[dict_idx++] = c;
301     *dest++ = c;
302     idx &= 0xfff;
303     dict_idx &= 0xfff;
304     }
305     }
306     }
307     }
308    
309    
310     /*
311     * Main program
312     */
313    
314     static void usage(const char *prg_name)
315     {
316     printf("Usage: %s [OPTION...]\n", prg_name);
317     printf("\nUnix options:\n");
318     printf(" --display STRING\n X display to use\n");
319     PrefsPrintUsage();
320     exit(0);
321     }
322    
323     int main(int argc, char **argv)
324     {
325     char str[256];
326     uint32 *boot_globs;
327     int16 i16;
328     int drive, driver;
329     int rom_fd;
330     FILE *proc_file;
331     const char *rom_path;
332     uint32 rom_size, actual;
333     uint8 *rom_tmp;
334     time_t now, expire;
335    
336     // Initialize variables
337     RAMBase = 0;
338     mmap_RAMBase = NULL;
339     tzset();
340    
341     // Print some info
342     printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
343     printf(" %s\n", GetString(STR_ABOUT_TEXT2));
344    
345     #if !EMULATED_PPC
346     // Get TOC pointer
347     TOC = get_toc();
348     #endif
349    
350     #ifdef ENABLE_GTK
351     // Init GTK
352     gtk_set_locale();
353     gtk_init(&argc, &argv);
354     #endif
355    
356     // Read preferences
357     PrefsInit(argc, argv);
358    
359     // Parse command line arguments
360     for (int i=1; i<argc; i++) {
361     if (strcmp(argv[i], "--help") == 0) {
362     usage(argv[0]);
363     } else if (strcmp(argv[i], "--display") == 0) {
364     i++;
365     if (i < argc)
366     x_display_name = strdup(argv[i]);
367     } else if (argv[i][0] == '-') {
368     fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
369     usage(argv[0]);
370     }
371     }
372    
373     // Open display
374     x_display = XOpenDisplay(x_display_name);
375     if (x_display == NULL) {
376     char str[256];
377     sprintf(str, GetString(STR_NO_XSERVER_ERR), XDisplayName(x_display_name));
378     ErrorAlert(str);
379     goto quit;
380     }
381    
382     #if defined(ENABLE_XF86_DGA) && !defined(ENABLE_MON)
383     // Fork out, so we can return from fullscreen mode when things get ugly
384     XF86DGAForkApp(DefaultScreen(x_display));
385     #endif
386    
387     #ifdef ENABLE_MON
388     // Initialize mon
389     mon_init();
390     #endif
391    
392     // Get system info
393     PVR = 0x00040000; // Default: 604
394     CPUClockSpeed = 100000000; // Default: 100MHz
395     BusClockSpeed = 100000000; // Default: 100MHz
396     #if !EMULATED_PPC
397     proc_file = fopen("/proc/cpuinfo", "r");
398     if (proc_file) {
399     char line[256];
400     while(fgets(line, 255, proc_file)) {
401     // Read line
402     int len = strlen(line);
403     if (len == 0)
404     continue;
405     line[len-1] = 0;
406    
407     // Parse line
408     int i;
409     char value[256];
410     if (sscanf(line, "cpu : %s", value) == 1) {
411     if (strcmp(value, "601") == 0)
412     PVR = 0x00010000;
413     else if (strcmp(value, "603") == 0)
414     PVR = 0x00030000;
415     else if (strcmp(value, "604") == 0)
416     PVR = 0x00040000;
417     else if (strcmp(value, "603e") == 0)
418     PVR = 0x00060000;
419     else if (strcmp(value, "603ev") == 0)
420     PVR = 0x00070000;
421     else if (strcmp(value, "604e") == 0)
422     PVR = 0x00090000;
423     else if (strcmp(value, "604ev5") == 0)
424     PVR = 0x000a0000;
425     else if (strcmp(value, "750") == 0)
426     PVR = 0x00080000;
427     else if (strcmp(value, "821") == 0)
428     PVR = 0x00320000;
429     else if (strcmp(value, "860") == 0)
430     PVR = 0x00500000;
431     else
432     printf("WARNING: Unknown CPU type '%s', assuming 604\n", value);
433     }
434     if (sscanf(line, "clock : %dMHz", &i) == 1)
435     CPUClockSpeed = BusClockSpeed = i * 1000000;
436     }
437     fclose(proc_file);
438     } else {
439     sprintf(str, GetString(STR_PROC_CPUINFO_WARN), strerror(errno));
440     WarningAlert(str);
441     }
442     #endif
443     D(bug("PVR: %08x (assumed)\n", PVR));
444    
445     // Init system routines
446     SysInit();
447    
448     // Show preferences editor
449     if (!PrefsFindBool("nogui"))
450     if (!PrefsEditor())
451     goto quit;
452    
453     #if !EMULATED_PPC
454     // Check some things
455     paranoia_check();
456     #endif
457    
458     // Open /dev/zero
459     zero_fd = open("/dev/zero", O_RDWR);
460     if (zero_fd < 0) {
461     sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
462     ErrorAlert(str);
463     goto quit;
464     }
465    
466     // Create Low Memory area (0x0000..0x3000)
467     if (mmap((char *)0x0000, 0x3000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
468     sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
469     ErrorAlert(str);
470     goto quit;
471     }
472     lm_area_mapped = true;
473    
474     // Create areas for Kernel Data
475     kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600);
476     if (kernel_area == -1) {
477     sprintf(str, GetString(STR_KD_SHMGET_ERR), strerror(errno));
478     ErrorAlert(str);
479     goto quit;
480     }
481     if (shmat(kernel_area, (void *)KERNEL_DATA_BASE, 0) < 0) {
482     sprintf(str, GetString(STR_KD_SHMAT_ERR), strerror(errno));
483     ErrorAlert(str);
484     goto quit;
485     }
486     if (shmat(kernel_area, (void *)KERNEL_DATA2_BASE, 0) < 0) {
487     sprintf(str, GetString(STR_KD2_SHMAT_ERR), strerror(errno));
488     ErrorAlert(str);
489     goto quit;
490     }
491     kernel_data = (KernelData *)0x68ffe000;
492     emulator_data = &kernel_data->ed;
493     KernelDataAddr = (uint32)kernel_data;
494     D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
495    
496     // Create area for Mac ROM
497     if (mmap((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
498     sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
499     ErrorAlert(str);
500     goto quit;
501     }
502     rom_area_mapped = true;
503     D(bug("ROM area at %08x\n", ROM_BASE));
504    
505     // Create area for Mac RAM
506     RAMSize = PrefsFindInt32("ramsize");
507     if (RAMSize < 8*1024*1024) {
508     WarningAlert(GetString(STR_SMALL_RAM_WARN));
509     RAMSize = 8*1024*1024;
510     }
511    
512     mmap_RAMBase = mmap((void *)0x20000000, RAMSize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0);
513     if (mmap_RAMBase == (void *)-1) {
514     sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
515     ErrorAlert(str);
516     goto quit;
517     }
518     RAMBase = (uint32)mmap_RAMBase;
519     ram_area_mapped = true;
520     D(bug("RAM area at %08x\n", RAMBase));
521    
522     if (RAMBase > ROM_BASE) {
523     ErrorAlert(GetString(STR_RAM_HIGHER_THAN_ROM_ERR));
524     goto quit;
525     }
526    
527     // Load Mac ROM
528     rom_path = PrefsFindString("rom");
529     rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
530     if (rom_fd < 0) {
531     rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME2, O_RDONLY);
532     if (rom_fd < 0) {
533     ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
534     goto quit;
535     }
536     }
537     printf(GetString(STR_READING_ROM_FILE));
538     rom_size = lseek(rom_fd, 0, SEEK_END);
539     lseek(rom_fd, 0, SEEK_SET);
540     rom_tmp = new uint8[ROM_SIZE];
541     actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
542     close(rom_fd);
543     if (actual == ROM_SIZE) {
544     // Plain ROM image
545     memcpy((void *)ROM_BASE, rom_tmp, ROM_SIZE);
546     delete[] rom_tmp;
547     } else {
548     if (strncmp((char *)rom_tmp, "<CHRP-BOOT>", 11) == 0) {
549     // CHRP compressed ROM image
550     D(bug("CHRP ROM image\n"));
551     uint32 lzss_offset, lzss_size;
552    
553     char *s = strstr((char *)rom_tmp, "constant lzss-offset");
554     if (s == NULL) {
555     ErrorAlert(GetString(STR_ROM_SIZE_ERR));
556     goto quit;
557     }
558     s -= 7;
559     if (sscanf(s, "%06x", &lzss_offset) != 1) {
560     ErrorAlert(GetString(STR_ROM_SIZE_ERR));
561     goto quit;
562     }
563     s = strstr((char *)rom_tmp, "constant lzss-size");
564     if (s == NULL) {
565     ErrorAlert(GetString(STR_ROM_SIZE_ERR));
566     goto quit;
567     }
568     s -= 7;
569     if (sscanf(s, "%06x", &lzss_size) != 1) {
570     ErrorAlert(GetString(STR_ROM_SIZE_ERR));
571     goto quit;
572     }
573     D(bug("Offset of compressed data: %08x\n", lzss_offset));
574     D(bug("Size of compressed data: %08x\n", lzss_size));
575    
576     D(bug("Uncompressing ROM...\n"));
577     decode_lzss(rom_tmp + lzss_offset, (uint8 *)ROM_BASE, lzss_size);
578     delete[] rom_tmp;
579     } else if (rom_size != 4*1024*1024) {
580     ErrorAlert(GetString(STR_ROM_SIZE_ERR));
581     goto quit;
582     } else {
583     ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
584     goto quit;
585     }
586     }
587    
588     // Load NVRAM
589     XPRAMInit();
590    
591     // Set boot volume
592     drive = PrefsFindInt32("bootdrive");
593     XPRAM[0x1378] = i16 >> 8;
594     XPRAM[0x1379] = i16 & 0xff;
595     driver = PrefsFindInt32("bootdriver");
596     XPRAM[0x137a] = i16 >> 8;
597     XPRAM[0x137b] = i16 & 0xff;
598    
599     // Create BootGlobs at top of Mac memory
600     memset((void *)(RAMBase + RAMSize - 4096), 0, 4096);
601     BootGlobsAddr = RAMBase + RAMSize - 0x1c;
602     boot_globs = (uint32 *)BootGlobsAddr;
603     boot_globs[-5] = htonl(RAMBase + RAMSize); // MemTop
604     boot_globs[0] = htonl(RAMBase); // First RAM bank
605     boot_globs[1] = htonl(RAMSize);
606     boot_globs[2] = htonl((uint32)-1); // End of bank table
607    
608     // Init drivers
609     SonyInit();
610     DiskInit();
611     CDROMInit();
612     SCSIInit();
613    
614     // Init external file system
615     ExtFSInit();
616    
617     // Init audio
618     AudioInit();
619    
620     // Init network
621     EtherInit();
622    
623     // Init serial ports
624     SerialInit();
625    
626     // Init Time Manager
627     TimerInit();
628    
629     // Init clipboard
630     ClipInit();
631    
632     // Init video
633     if (!VideoInit())
634     goto quit;
635    
636     // Install ROM patches
637     if (!PatchROM()) {
638     ErrorAlert(GetString(STR_UNSUPPORTED_ROM_TYPE_ERR));
639     goto quit;
640     }
641    
642     // Clear caches (as we loaded and patched code) and write protect ROM
643     #if !EMULATED_PPC
644     MakeExecutable(0, (void *)ROM_BASE, ROM_AREA_SIZE);
645     #endif
646     mprotect((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ);
647    
648     // Initialize Kernel Data
649     memset(kernel_data, 0, sizeof(KernelData));
650     if (ROMType == ROMTYPE_NEWWORLD) {
651     static uint32 of_dev_tree[4] = {0, 0, 0, 0};
652     static uint8 vector_lookup_tbl[128];
653     static uint8 vector_mask_tbl[64];
654     memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80);
655     memset(vector_lookup_tbl, 0, 128);
656     memset(vector_mask_tbl, 0, 64);
657     kernel_data->v[0xb80 >> 2] = htonl(ROM_BASE);
658     kernel_data->v[0xb84 >> 2] = htonl((uint32)of_dev_tree); // OF device tree base
659     kernel_data->v[0xb90 >> 2] = htonl((uint32)vector_lookup_tbl);
660     kernel_data->v[0xb94 >> 2] = htonl((uint32)vector_mask_tbl);
661     kernel_data->v[0xb98 >> 2] = htonl(ROM_BASE); // OpenPIC base
662     kernel_data->v[0xbb0 >> 2] = htonl(0); // ADB base
663     kernel_data->v[0xc20 >> 2] = htonl(RAMSize);
664     kernel_data->v[0xc24 >> 2] = htonl(RAMSize);
665     kernel_data->v[0xc30 >> 2] = htonl(RAMSize);
666     kernel_data->v[0xc34 >> 2] = htonl(RAMSize);
667     kernel_data->v[0xc38 >> 2] = htonl(0x00010020);
668     kernel_data->v[0xc3c >> 2] = htonl(0x00200001);
669     kernel_data->v[0xc40 >> 2] = htonl(0x00010000);
670     kernel_data->v[0xc50 >> 2] = htonl(RAMBase);
671     kernel_data->v[0xc54 >> 2] = htonl(RAMSize);
672     kernel_data->v[0xf60 >> 2] = htonl(PVR);
673     kernel_data->v[0xf64 >> 2] = htonl(CPUClockSpeed);
674     kernel_data->v[0xf68 >> 2] = htonl(BusClockSpeed);
675     kernel_data->v[0xf6c >> 2] = htonl(CPUClockSpeed);
676     } else {
677     kernel_data->v[0xc80 >> 2] = htonl(RAMSize);
678     kernel_data->v[0xc84 >> 2] = htonl(RAMSize);
679     kernel_data->v[0xc90 >> 2] = htonl(RAMSize);
680     kernel_data->v[0xc94 >> 2] = htonl(RAMSize);
681     kernel_data->v[0xc98 >> 2] = htonl(0x00010020);
682     kernel_data->v[0xc9c >> 2] = htonl(0x00200001);
683     kernel_data->v[0xca0 >> 2] = htonl(0x00010000);
684     kernel_data->v[0xcb0 >> 2] = htonl(RAMBase);
685     kernel_data->v[0xcb4 >> 2] = htonl(RAMSize);
686     kernel_data->v[0xf80 >> 2] = htonl(PVR);
687     kernel_data->v[0xf84 >> 2] = htonl(CPUClockSpeed);
688     kernel_data->v[0xf88 >> 2] = htonl(BusClockSpeed);
689     kernel_data->v[0xf8c >> 2] = htonl(CPUClockSpeed);
690     }
691    
692     // Initialize extra low memory
693     D(bug("Initializing Low Memory...\n"));
694     memset(NULL, 0, 0x3000);
695     WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h')); // Signature to detect SheepShaver
696     WriteMacInt32(XLM_KERNEL_DATA, (uint32)kernel_data); // For trap replacement routines
697     WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR
698     WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch
699     WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
700     #if !EMULATED_PPC
701     WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator
702     WriteMacInt32(XLM_ETHER_INIT, (uint32)InitStreamModule); // DLPI ethernet driver functions
703     WriteMacInt32(XLM_ETHER_TERM, (uint32)TerminateStreamModule);
704     WriteMacInt32(XLM_ETHER_OPEN, (uint32)ether_open);
705     WriteMacInt32(XLM_ETHER_CLOSE, (uint32)ether_close);
706     WriteMacInt32(XLM_ETHER_WPUT, (uint32)ether_wput);
707     WriteMacInt32(XLM_ETHER_RSRV, (uint32)ether_rsrv);
708     WriteMacInt32(XLM_VIDEO_DOIO, (uint32)VideoDoDriverIO);
709     #endif
710     D(bug("Low Memory initialized\n"));
711    
712     // Start 60Hz thread
713     tick_thread_active = (pthread_create(&tick_thread, NULL, tick_func, NULL) == 0);
714     D(bug("Tick thread installed (%ld)\n", tick_thread));
715    
716     // Start NVRAM watchdog thread
717     memcpy(last_xpram, XPRAM, XPRAM_SIZE);
718     nvram_thread_active = (pthread_create(&nvram_thread, NULL, nvram_func, NULL) == 0);
719     D(bug("NVRAM thread installed (%ld)\n", nvram_thread));
720    
721     #if !EMULATED_PPC
722     // Create and install stacks for signal handlers
723     sig_stack = malloc(SIG_STACK_SIZE);
724     D(bug("Signal stack at %p\n", sig_stack));
725     if (sig_stack == NULL) {
726     ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
727     goto quit;
728     }
729     extra_stack = malloc(SIG_STACK_SIZE);
730     D(bug("Extra stack at %p\n", extra_stack));
731     if (extra_stack == NULL) {
732     ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
733     goto quit;
734     }
735     struct sigaltstack new_stack;
736     new_stack.ss_sp = sig_stack;
737     new_stack.ss_flags = 0;
738     new_stack.ss_size = SIG_STACK_SIZE;
739     if (sigaltstack(&new_stack, NULL) < 0) {
740     sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
741     ErrorAlert(str);
742     goto quit;
743     }
744     #endif
745    
746     #if !EMULATED_PPC
747     // Install SIGSEGV handler
748     sigemptyset(&sigsegv_action.sa_mask); // Block interrupts during SEGV handling
749     sigaddset(&sigsegv_action.sa_mask, SIGUSR2);
750     sigsegv_action.sa_handler = (__sighandler_t)sigsegv_handler;
751     sigsegv_action.sa_flags = SA_ONSTACK;
752     sigsegv_action.sa_restorer = NULL;
753     if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) {
754     sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno));
755     ErrorAlert(str);
756     goto quit;
757     }
758    
759     // Install SIGILL handler
760     sigemptyset(&sigill_action.sa_mask); // Block interrupts during ILL handling
761     sigaddset(&sigill_action.sa_mask, SIGUSR2);
762     sigill_action.sa_handler = (__sighandler_t)sigill_handler;
763     sigill_action.sa_flags = SA_ONSTACK;
764     sigill_action.sa_restorer = NULL;
765     if (sigaction(SIGILL, &sigill_action, NULL) < 0) {
766     sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno));
767     ErrorAlert(str);
768     goto quit;
769     }
770    
771     // Install interrupt signal handler
772     sigemptyset(&sigusr2_action.sa_mask);
773     sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler;
774     sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART;
775     sigusr2_action.sa_restorer = NULL;
776     if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
777     sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
778     ErrorAlert(str);
779     goto quit;
780     }
781     #endif
782    
783     // Get my thread ID and execute MacOS thread function
784     emul_thread = pthread_self();
785     D(bug("MacOS thread is %ld\n", emul_thread));
786     emul_func(NULL);
787    
788     quit:
789     Quit();
790     return 0;
791     }
792    
793    
794     /*
795     * Cleanup and quit
796     */
797    
798     static void Quit(void)
799     {
800     // Stop 60Hz thread
801     if (tick_thread_active) {
802     pthread_cancel(tick_thread);
803     pthread_join(tick_thread, NULL);
804     }
805    
806     // Stop NVRAM watchdog thread
807     if (nvram_thread_active) {
808     pthread_cancel(nvram_thread);
809     pthread_join(nvram_thread, NULL);
810     }
811    
812     #if !EMULATED_PPC
813     // Uninstall SIGSEGV handler
814     sigemptyset(&sigsegv_action.sa_mask);
815     sigsegv_action.sa_handler = SIG_DFL;
816     sigsegv_action.sa_flags = 0;
817     sigaction(SIGSEGV, &sigsegv_action, NULL);
818    
819     // Uninstall SIGILL handler
820     sigemptyset(&sigill_action.sa_mask);
821     sigill_action.sa_handler = SIG_DFL;
822     sigill_action.sa_flags = 0;
823     sigaction(SIGILL, &sigill_action, NULL);
824     #endif
825    
826     // Save NVRAM
827     XPRAMExit();
828    
829     // Exit clipboard
830     ClipExit();
831    
832     // Exit Time Manager
833     TimerExit();
834    
835     // Exit serial
836     SerialExit();
837    
838     // Exit network
839     EtherExit();
840    
841     // Exit audio
842     AudioExit();
843    
844     // Exit video
845     VideoExit();
846    
847     // Exit external file system
848     ExtFSExit();
849    
850     // Exit drivers
851     SCSIExit();
852     CDROMExit();
853     DiskExit();
854     SonyExit();
855    
856     // Delete RAM area
857     if (ram_area_mapped)
858     munmap(mmap_RAMBase, RAMSize);
859    
860     // Delete ROM area
861     if (rom_area_mapped)
862     munmap((char *)ROM_BASE, ROM_AREA_SIZE);
863    
864     // Delete Kernel Data area
865     if (kernel_area >= 0) {
866     shmdt((void *)KERNEL_DATA_BASE);
867     shmdt((void *)KERNEL_DATA2_BASE);
868     shmctl(kernel_area, IPC_RMID, NULL);
869     }
870    
871     // Delete Low Memory area
872     if (lm_area_mapped)
873     munmap((char *)0x0000, 0x3000);
874    
875     // Close /dev/zero
876     if (zero_fd > 0)
877     close(zero_fd);
878    
879     // Exit system routines
880     SysExit();
881    
882     // Exit preferences
883     PrefsExit();
884    
885     #ifdef ENABLE_MON
886     // Exit mon
887     mon_exit();
888     #endif
889    
890     // Close X11 server connection
891     if (x_display)
892     XCloseDisplay(x_display);
893    
894     exit(0);
895     }
896    
897    
898     /*
899     * Jump into Mac ROM, start 680x0 emulator
900     */
901    
902     #if EMULATED_PPC
903     extern void emul_ppc(uint32 start);
904     extern void init_emul_ppc(void);
905     void jump_to_rom(uint32 entry)
906     {
907     init_emul_ppc();
908     emul_ppc(entry);
909     }
910     #endif
911    
912    
913     /*
914     * Emulator thread function
915     */
916    
917     static void *emul_func(void *arg)
918     {
919     // We're now ready to receive signals
920     ready_for_signals = true;
921    
922     // Decrease priority, so more time-critical things like audio will work better
923     nice(1);
924    
925     // Jump to ROM boot routine
926     D(bug("Jumping to ROM\n"));
927     #if EMULATED_PPC
928     jump_to_rom(ROM_BASE + 0x310000);
929     #else
930     jump_to_rom(ROM_BASE + 0x310000, (uint32)emulator_data);
931     #endif
932     D(bug("Returned from ROM\n"));
933    
934     // We're no longer ready to receive signals
935     ready_for_signals = false;
936     return NULL;
937     }
938    
939    
940     #if !EMULATED_PPC
941     /*
942     * Execute 68k subroutine (must be ended with RTS)
943     * This must only be called by the emul_thread when in EMUL_OP mode
944     * r->a[7] is unused, the routine runs on the caller's stack
945     */
946    
947     void Execute68k(uint32 pc, M68kRegisters *r)
948     {
949     #if SAFE_EXEC_68K
950     if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP)
951     printf("FATAL: Execute68k() not called from EMUL_OP mode\n");
952     if (!pthread_equal(pthread_self(), emul_thread))
953     printf("FATAL: Execute68k() not called from emul_thread\n");
954     #endif
955     execute_68k(pc, r);
956     }
957    
958    
959     /*
960     * Execute 68k A-Trap from EMUL_OP routine
961     * r->a[7] is unused, the routine runs on the caller's stack
962     */
963    
964     void Execute68kTrap(uint16 trap, M68kRegisters *r)
965     {
966     uint16 proc[2] = {trap, M68K_RTS};
967     Execute68k((uint32)proc, r);
968     }
969     #endif
970    
971    
972     /*
973     * Execute PPC code from EMUL_OP routine (real mode switch)
974     */
975    
976     void ExecutePPC(void (*func)())
977     {
978     uint32 tvect[2] = {(uint32)func, 0}; // Fake TVECT
979     RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, tvect);
980     M68kRegisters r;
981     Execute68k((uint32)&desc, &r);
982     }
983    
984    
985     /*
986     * Quit emulator (cause return from jump_to_rom)
987     */
988    
989     void QuitEmulator(void)
990     {
991     #if EMULATED_PPC
992     Quit();
993     #else
994     quit_emulator();
995     #endif
996     }
997    
998    
999     /*
1000     * Pause/resume emulator
1001     */
1002    
1003     void PauseEmulator(void)
1004     {
1005     pthread_kill(emul_thread, SIGSTOP);
1006     }
1007    
1008     void ResumeEmulator(void)
1009     {
1010     pthread_kill(emul_thread, SIGCONT);
1011     }
1012    
1013    
1014     /*
1015     * Dump 68k registers
1016     */
1017    
1018     void Dump68kRegs(M68kRegisters *r)
1019     {
1020     // Display 68k registers
1021     for (int i=0; i<8; i++) {
1022     printf("d%d: %08x", i, r->d[i]);
1023     if (i == 3 || i == 7)
1024     printf("\n");
1025     else
1026     printf(", ");
1027     }
1028     for (int i=0; i<8; i++) {
1029     printf("a%d: %08x", i, r->a[i]);
1030     if (i == 3 || i == 7)
1031     printf("\n");
1032     else
1033     printf(", ");
1034     }
1035     }
1036    
1037    
1038     /*
1039     * Make code executable
1040     */
1041    
1042     void MakeExecutable(int dummy, void *start, uint32 length)
1043     {
1044     #if !EMULATED_PPC
1045     if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE)))
1046     return;
1047     flush_icache_range(start, (void *)((uint32)start + length));
1048     #endif
1049     }
1050    
1051    
1052     /*
1053     * Patch things after system startup (gets called by disk driver accRun routine)
1054     */
1055    
1056     void PatchAfterStartup(void)
1057     {
1058     ExecutePPC(VideoInstallAccel);
1059     InstallExtFS();
1060     }
1061    
1062    
1063     /*
1064     * NVRAM watchdog thread (saves NVRAM every minute)
1065     */
1066    
1067     static void *nvram_func(void *arg)
1068     {
1069     struct timespec req = {60, 0}; // 1 minute
1070    
1071     for (;;) {
1072     pthread_testcancel();
1073     nanosleep(&req, NULL);
1074     pthread_testcancel();
1075     if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
1076     memcpy(last_xpram, XPRAM, XPRAM_SIZE);
1077     SaveXPRAM();
1078     }
1079     }
1080     return NULL;
1081     }
1082    
1083    
1084     /*
1085     * 60Hz thread (really 60.15Hz)
1086     */
1087    
1088     static void *tick_func(void *arg)
1089     {
1090     int tick_counter = 0;
1091     struct timespec req = {0, 16625000};
1092    
1093     for (;;) {
1094    
1095     // Wait
1096     nanosleep(&req, NULL);
1097    
1098     #if !EMULATED_PPC
1099     // Did we crash?
1100     if (emul_thread_fatal) {
1101    
1102     // Yes, dump registers
1103     pt_regs *r = (pt_regs *)&sigsegv_regs;
1104     char str[256];
1105     sprintf(str, "SIGSEGV\n"
1106     " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
1107     " xer %08lx cr %08lx \n"
1108     " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
1109     " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
1110     " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
1111     " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
1112     " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
1113     " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
1114     " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
1115     " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
1116     r->nip, r->link, r->ctr, r->msr,
1117     r->xer, r->ccr,
1118     r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3],
1119     r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7],
1120     r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11],
1121     r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15],
1122     r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19],
1123     r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23],
1124     r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27],
1125     r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]);
1126     printf(str);
1127     VideoQuitFullScreen();
1128    
1129     #ifdef ENABLE_MON
1130     // Start up mon in real-mode
1131     printf("Welcome to the sheep factory.\n");
1132     char *arg[4] = {"mon", "-m", "-r", NULL};
1133     mon(3, arg);
1134     #endif
1135     return NULL;
1136     }
1137     #endif
1138    
1139     // Pseudo Mac 1Hz interrupt, update local time
1140     if (++tick_counter > 60) {
1141     tick_counter = 0;
1142     WriteMacInt32(0x20c, TimerDateTime());
1143     }
1144    
1145     // Trigger 60Hz interrupt
1146     if (ReadMacInt32(XLM_IRQ_NEST) == 0) {
1147     SetInterruptFlag(INTFLAG_VIA);
1148     TriggerInterrupt();
1149     }
1150     }
1151     return NULL;
1152     }
1153    
1154    
1155     /*
1156     * Mutexes
1157     */
1158    
1159     struct B2_mutex {
1160     int dummy;
1161     };
1162    
1163     B2_mutex *B2_create_mutex(void)
1164     {
1165     return new B2_mutex;
1166     }
1167    
1168     void B2_lock_mutex(B2_mutex *mutex)
1169     {
1170     }
1171    
1172     void B2_unlock_mutex(B2_mutex *mutex)
1173     {
1174     }
1175    
1176     void B2_delete_mutex(B2_mutex *mutex)
1177     {
1178     delete mutex;
1179     }
1180    
1181    
1182     /*
1183     * Trigger signal USR2 from another thread
1184     */
1185    
1186     void TriggerInterrupt(void)
1187     {
1188     #if EMULATED_PPC
1189     WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1190     #else
1191     #if 0
1192     WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1193     #else
1194     if (ready_for_signals)
1195     pthread_kill(emul_thread, SIGUSR2);
1196     #endif
1197     #endif
1198     }
1199    
1200    
1201     /*
1202     * Interrupt flags (must be handled atomically!)
1203     */
1204    
1205     volatile uint32 InterruptFlags = 0;
1206    
1207     void SetInterruptFlag(uint32 flag)
1208     {
1209     atomic_or((int *)&InterruptFlags, flag);
1210     }
1211    
1212     void ClearInterruptFlag(uint32 flag)
1213     {
1214     atomic_and((int *)&InterruptFlags, ~flag);
1215     }
1216    
1217    
1218     /*
1219     * Disable interrupts
1220     */
1221    
1222     void DisableInterrupt(void)
1223     {
1224     atomic_add((int *)XLM_IRQ_NEST, 1);
1225     }
1226    
1227    
1228     /*
1229     * Enable interrupts
1230     */
1231    
1232     void EnableInterrupt(void)
1233     {
1234     atomic_add((int *)XLM_IRQ_NEST, -1);
1235     }
1236    
1237    
1238     #if !EMULATED_PPC
1239     /*
1240     * USR2 handler
1241     */
1242    
1243     static void sigusr2_handler(int sig, sigcontext_struct *sc)
1244     {
1245     pt_regs *r = sc->regs;
1246    
1247     // Do nothing if interrupts are disabled
1248     if (*(int32 *)XLM_IRQ_NEST > 0)
1249     return;
1250    
1251     // Disable MacOS stack sniffer
1252     WriteMacInt32(0x110, 0);
1253    
1254     // Interrupt action depends on current run mode
1255     switch (ReadMacInt32(XLM_RUN_MODE)) {
1256     case MODE_68K:
1257     // 68k emulator active, trigger 68k interrupt level 1
1258     WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
1259     r->ccr |= ntohl(kernel_data->v[0x674 >> 2]);
1260     break;
1261    
1262     #if INTERRUPTS_IN_NATIVE_MODE
1263     case MODE_NATIVE:
1264     // 68k emulator inactive, in nanokernel?
1265     if (r->gpr[1] != KernelDataAddr) {
1266     // Prepare for 68k interrupt level 1
1267     WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
1268     WriteMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc, ReadMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc) | ntohl(kernel_data->v[0x674 >> 2]));
1269    
1270     // Execute nanokernel interrupt routine (this will activate the 68k emulator)
1271     atomic_add((int32 *)XLM_IRQ_NEST, 1);
1272     if (ROMType == ROMTYPE_NEWWORLD)
1273     ppc_interrupt(ROM_BASE + 0x312b1c, KernelDataAddr);
1274     else
1275     ppc_interrupt(ROM_BASE + 0x312a3c, KernelDataAddr);
1276     }
1277     break;
1278     #endif
1279    
1280     #if INTERRUPTS_IN_EMUL_OP_MODE
1281     case MODE_EMUL_OP:
1282     // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0
1283     if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1284    
1285     // Set extra stack for SIGSEGV handler
1286     struct sigaltstack new_stack;
1287     new_stack.ss_sp = extra_stack;
1288     new_stack.ss_flags = 0;
1289     new_stack.ss_size = SIG_STACK_SIZE;
1290     sigaltstack(&new_stack, NULL);
1291     #if 1
1292     // Execute full 68k interrupt routine
1293     M68kRegisters r;
1294     uint32 old_r25 = ReadMacInt32(XLM_68K_R25); // Save interrupt level
1295     WriteMacInt32(XLM_68K_R25, 0x21); // Execute with interrupt level 1
1296     static const uint16 proc[] = {
1297     0x3f3c, 0x0000, // move.w #$0000,-(sp) (fake format word)
1298     0x487a, 0x000a, // pea @1(pc) (return address)
1299     0x40e7, // move sr,-(sp) (saved SR)
1300     0x2078, 0x0064, // move.l $64,a0
1301     0x4ed0, // jmp (a0)
1302     M68K_RTS // @1
1303     };
1304     Execute68k((uint32)proc, &r);
1305     WriteMacInt32(XLM_68K_R25, old_r25); // Restore interrupt level
1306     #else
1307     // Only update cursor
1308     if (HasMacStarted()) {
1309     if (InterruptFlags & INTFLAG_VIA) {
1310     ClearInterruptFlag(INTFLAG_VIA);
1311     ADBInterrupt();
1312     ExecutePPC(VideoVBL);
1313     }
1314     }
1315     #endif
1316     // Reset normal signal stack
1317     new_stack.ss_sp = sig_stack;
1318     new_stack.ss_flags = 0;
1319     new_stack.ss_size = SIG_STACK_SIZE;
1320     sigaltstack(&new_stack, NULL);
1321     }
1322     break;
1323     #endif
1324    
1325     }
1326     }
1327    
1328    
1329     /*
1330     * SIGSEGV handler
1331     */
1332    
1333     static void sigsegv_handler(int sig, sigcontext_struct *sc)
1334     {
1335     pt_regs *r = sc->regs;
1336     num_segv++;
1337    
1338     // Fault in Mac ROM or RAM?
1339     bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize));
1340     if (mac_fault) {
1341    
1342     // Get opcode and divide into fields
1343     uint32 opcode = *((uint32 *)r->nip);
1344     uint32 primop = opcode >> 26;
1345     uint32 exop = (opcode >> 1) & 0x3ff;
1346     uint32 ra = (opcode >> 16) & 0x1f;
1347     uint32 rb = (opcode >> 11) & 0x1f;
1348     uint32 rd = (opcode >> 21) & 0x1f;
1349     int32 imm = (int16)(opcode & 0xffff);
1350    
1351     // "VM settings" during MacOS 8 installation
1352     if (r->nip == ROM_BASE + 0x488160 && r->gpr[20] == 0xf8000000) {
1353     r->nip += 4;
1354     r->gpr[8] = 0;
1355     return;
1356    
1357     // MacOS 8.5 installation
1358     } else if (r->nip == ROM_BASE + 0x488140 && r->gpr[16] == 0xf8000000) {
1359     r->nip += 4;
1360     r->gpr[8] = 0;
1361     return;
1362    
1363     // MacOS 8 serial drivers on startup
1364     } else if (r->nip == ROM_BASE + 0x48e080 && (r->gpr[8] == 0xf3012002 || r->gpr[8] == 0xf3012000)) {
1365     r->nip += 4;
1366     r->gpr[8] = 0;
1367     return;
1368    
1369     // MacOS 8.1 serial drivers on startup
1370     } else if (r->nip == ROM_BASE + 0x48c5e0 && (r->gpr[20] == 0xf3012002 || r->gpr[20] == 0xf3012000)) {
1371     r->nip += 4;
1372     return;
1373     } else if (r->nip == ROM_BASE + 0x4a10a0 && (r->gpr[20] == 0xf3012002 || r->gpr[20] == 0xf3012000)) {
1374     r->nip += 4;
1375     return;
1376     }
1377    
1378     // Analyze opcode
1379     enum {
1380     TYPE_UNKNOWN,
1381     TYPE_LOAD,
1382     TYPE_STORE
1383     } transfer_type = TYPE_UNKNOWN;
1384     enum {
1385     SIZE_UNKNOWN,
1386     SIZE_BYTE,
1387     SIZE_HALFWORD,
1388     SIZE_WORD
1389     } transfer_size = SIZE_UNKNOWN;
1390     enum {
1391     MODE_UNKNOWN,
1392     MODE_NORM,
1393     MODE_U,
1394     MODE_X,
1395     MODE_UX
1396     } addr_mode = MODE_UNKNOWN;
1397     switch (primop) {
1398     case 31:
1399     switch (exop) {
1400     case 23: // lwzx
1401     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
1402     case 55: // lwzux
1403     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
1404     case 87: // lbzx
1405     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
1406     case 119: // lbzux
1407     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
1408     case 151: // stwx
1409     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
1410     case 183: // stwux
1411     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
1412     case 215: // stbx
1413     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
1414     case 247: // stbux
1415     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
1416     case 279: // lhzx
1417     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1418     case 311: // lhzux
1419     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1420     case 343: // lhax
1421     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1422     case 375: // lhaux
1423     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1424     case 407: // sthx
1425     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1426     case 439: // sthux
1427     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1428     }
1429     break;
1430    
1431     case 32: // lwz
1432     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
1433     case 33: // lwzu
1434     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
1435     case 34: // lbz
1436     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
1437     case 35: // lbzu
1438     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
1439     case 36: // stw
1440     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
1441     case 37: // stwu
1442     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
1443     case 38: // stb
1444     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
1445     case 39: // stbu
1446     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
1447     case 40: // lhz
1448     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1449     case 41: // lhzu
1450     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1451     case 42: // lha
1452     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1453     case 43: // lhau
1454     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1455     case 44: // sth
1456     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1457     case 45: // sthu
1458     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1459     }
1460    
1461     // Calculate effective address
1462     uint32 addr = 0;
1463     switch (addr_mode) {
1464     case MODE_X:
1465     case MODE_UX:
1466     if (ra == 0)
1467     addr = r->gpr[rb];
1468     else
1469     addr = r->gpr[ra] + r->gpr[rb];
1470     break;
1471     case MODE_NORM:
1472     case MODE_U:
1473     if (ra == 0)
1474     addr = (int32)(int16)imm;
1475     else
1476     addr = r->gpr[ra] + (int32)(int16)imm;
1477     break;
1478     default:
1479     break;
1480     }
1481    
1482     // Ignore ROM writes
1483     if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
1484     // 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));
1485     if (addr_mode == MODE_U || addr_mode == MODE_UX)
1486     r->gpr[ra] = addr;
1487     r->nip += 4;
1488     goto rti;
1489     }
1490    
1491     // Ignore illegal memory accesses?
1492     if (PrefsFindBool("ignoresegv")) {
1493     if (addr_mode == MODE_U || addr_mode == MODE_UX)
1494     r->gpr[ra] = addr;
1495     if (transfer_type == TYPE_LOAD)
1496     r->gpr[rd] = 0;
1497     r->nip += 4;
1498     goto rti;
1499     }
1500    
1501     // In GUI mode, show error alert
1502     if (!PrefsFindBool("nogui")) {
1503     char str[256];
1504     if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE)
1505     sprintf(str, GetString(STR_MEM_ACCESS_ERR), transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "halfword" : "word", transfer_type == TYPE_LOAD ? GetString(STR_MEM_ACCESS_READ) : GetString(STR_MEM_ACCESS_WRITE), addr, r->nip, r->gpr[24], r->gpr[1]);
1506     else
1507     sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->nip, r->gpr[24], r->gpr[1], opcode);
1508     ErrorAlert(str);
1509     QuitEmulator();
1510     return;
1511     }
1512     }
1513    
1514     // For all other errors, jump into debugger (sort of...)
1515     if (!ready_for_signals) {
1516     printf("SIGSEGV\n");
1517     printf(" sigcontext %p, pt_regs %p\n", sc, r);
1518     printf(
1519     " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
1520     " xer %08lx cr %08lx \n"
1521     " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
1522     " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
1523     " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
1524     " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
1525     " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
1526     " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
1527     " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
1528     " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
1529     r->nip, r->link, r->ctr, r->msr,
1530     r->xer, r->ccr,
1531     r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3],
1532     r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7],
1533     r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11],
1534     r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15],
1535     r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19],
1536     r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23],
1537     r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27],
1538     r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]);
1539     exit(1);
1540     QuitEmulator();
1541     return;
1542     } else {
1543     // We crashed. Save registers, tell tick thread and loop forever
1544     sigsegv_regs = *(sigregs *)r;
1545     emul_thread_fatal = true;
1546     for (;;) ;
1547     }
1548     rti:;
1549     }
1550    
1551    
1552     /*
1553     * SIGILL handler
1554     */
1555    
1556     static void sigill_handler(int sig, sigcontext_struct *sc)
1557     {
1558     pt_regs *r = sc->regs;
1559     char str[256];
1560    
1561     // Fault in Mac ROM or RAM?
1562     bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize));
1563     if (mac_fault) {
1564    
1565     // Get opcode and divide into fields
1566     uint32 opcode = *((uint32 *)r->nip);
1567     uint32 primop = opcode >> 26;
1568     uint32 exop = (opcode >> 1) & 0x3ff;
1569     uint32 ra = (opcode >> 16) & 0x1f;
1570     uint32 rb = (opcode >> 11) & 0x1f;
1571     uint32 rd = (opcode >> 21) & 0x1f;
1572     int32 imm = (int16)(opcode & 0xffff);
1573    
1574     switch (primop) {
1575     case 9: // POWER instructions
1576     case 22:
1577     power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->nip, r->gpr[1], opcode);
1578     ErrorAlert(str);
1579     QuitEmulator();
1580     return;
1581    
1582     case 31:
1583     switch (exop) {
1584     case 83: // mfmsr
1585     r->gpr[rd] = 0xf072;
1586     r->nip += 4;
1587     goto rti;
1588    
1589     case 210: // mtsr
1590     case 242: // mtsrin
1591     case 306: // tlbie
1592     r->nip += 4;
1593     goto rti;
1594    
1595     case 339: { // mfspr
1596     int spr = ra | (rb << 5);
1597     switch (spr) {
1598     case 0: // MQ
1599     case 22: // DEC
1600     case 952: // MMCR0
1601     case 953: // PMC1
1602     case 954: // PMC2
1603     case 955: // SIA
1604     case 956: // MMCR1
1605     case 957: // PMC3
1606     case 958: // PMC4
1607     case 959: // SDA
1608     r->nip += 4;
1609     goto rti;
1610     case 25: // SDR1
1611     r->gpr[rd] = 0xdead001f;
1612     r->nip += 4;
1613     goto rti;
1614     case 287: // PVR
1615     r->gpr[rd] = PVR;
1616     r->nip += 4;
1617     goto rti;
1618     }
1619     break;
1620     }
1621    
1622     case 467: { // mtspr
1623     int spr = ra | (rb << 5);
1624     switch (spr) {
1625     case 0: // MQ
1626     case 22: // DEC
1627     case 275: // SPRG3
1628     case 528: // IBAT0U
1629     case 529: // IBAT0L
1630     case 530: // IBAT1U
1631     case 531: // IBAT1L
1632     case 532: // IBAT2U
1633     case 533: // IBAT2L
1634     case 534: // IBAT3U
1635     case 535: // IBAT3L
1636     case 536: // DBAT0U
1637     case 537: // DBAT0L
1638     case 538: // DBAT1U
1639     case 539: // DBAT1L
1640     case 540: // DBAT2U
1641     case 541: // DBAT2L
1642     case 542: // DBAT3U
1643     case 543: // DBAT3L
1644     case 952: // MMCR0
1645     case 953: // PMC1
1646     case 954: // PMC2
1647     case 955: // SIA
1648     case 956: // MMCR1
1649     case 957: // PMC3
1650     case 958: // PMC4
1651     case 959: // SDA
1652     r->nip += 4;
1653     goto rti;
1654     }
1655     break;
1656     }
1657    
1658     case 29: case 107: case 152: case 153: // POWER instructions
1659     case 184: case 216: case 217: case 248:
1660     case 264: case 277: case 331: case 360:
1661     case 363: case 488: case 531: case 537:
1662     case 541: case 664: case 665: case 696:
1663     case 728: case 729: case 760: case 920:
1664     case 921: case 952:
1665     goto power_inst;
1666     }
1667     }
1668    
1669     // In GUI mode, show error alert
1670     if (!PrefsFindBool("nogui")) {
1671     sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->nip, r->gpr[24], r->gpr[1], opcode);
1672     ErrorAlert(str);
1673     QuitEmulator();
1674     return;
1675     }
1676     }
1677    
1678     // For all other errors, jump into debugger (sort of...)
1679     if (!ready_for_signals) {
1680     printf("SIGILL\n");
1681     printf(" sigcontext %p, pt_regs %p\n", sc, r);
1682     printf(
1683     " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
1684     " xer %08lx cr %08lx \n"
1685     " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
1686     " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
1687     " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
1688     " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
1689     " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
1690     " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
1691     " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
1692     " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
1693     r->nip, r->link, r->ctr, r->msr,
1694     r->xer, r->ccr,
1695     r->gpr[0], r->gpr[1], r->gpr[2], r->gpr[3],
1696     r->gpr[4], r->gpr[5], r->gpr[6], r->gpr[7],
1697     r->gpr[8], r->gpr[9], r->gpr[10], r->gpr[11],
1698     r->gpr[12], r->gpr[13], r->gpr[14], r->gpr[15],
1699     r->gpr[16], r->gpr[17], r->gpr[18], r->gpr[19],
1700     r->gpr[20], r->gpr[21], r->gpr[22], r->gpr[23],
1701     r->gpr[24], r->gpr[25], r->gpr[26], r->gpr[27],
1702     r->gpr[28], r->gpr[29], r->gpr[30], r->gpr[31]);
1703     exit(1);
1704     QuitEmulator();
1705     return;
1706     } else {
1707     // We crashed. Save registers, tell tick thread and loop forever
1708     sigsegv_regs = *(sigregs *)r;
1709     emul_thread_fatal = true;
1710     for (;;) ;
1711     }
1712     rti:;
1713     }
1714     #endif
1715    
1716    
1717     /*
1718     * Display alert
1719     */
1720    
1721     #ifdef ENABLE_GTK
1722     static void dl_destroyed(void)
1723     {
1724     gtk_main_quit();
1725     }
1726    
1727     static void dl_quit(GtkWidget *dialog)
1728     {
1729     gtk_widget_destroy(dialog);
1730     }
1731    
1732     void display_alert(int title_id, int prefix_id, int button_id, const char *text)
1733     {
1734     char str[256];
1735     sprintf(str, GetString(prefix_id), text);
1736    
1737     GtkWidget *dialog = gtk_dialog_new();
1738     gtk_window_set_title(GTK_WINDOW(dialog), GetString(title_id));
1739     gtk_container_border_width(GTK_CONTAINER(dialog), 5);
1740     gtk_widget_set_uposition(GTK_WIDGET(dialog), 100, 150);
1741     gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(dl_destroyed), NULL);
1742    
1743     GtkWidget *label = gtk_label_new(str);
1744     gtk_widget_show(label);
1745     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
1746    
1747     GtkWidget *button = gtk_button_new_with_label(GetString(button_id));
1748     gtk_widget_show(button);
1749     gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(dl_quit), GTK_OBJECT(dialog));
1750     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0);
1751     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1752     gtk_widget_grab_default(button);
1753     gtk_widget_show(dialog);
1754    
1755     gtk_main();
1756     }
1757     #endif
1758    
1759    
1760     /*
1761     * Display error alert
1762     */
1763    
1764     void ErrorAlert(const char *text)
1765     {
1766     #ifdef ENABLE_GTK
1767     if (PrefsFindBool("nogui") || x_display == NULL) {
1768     printf(GetString(STR_SHELL_ERROR_PREFIX), text);
1769     return;
1770     }
1771     VideoQuitFullScreen();
1772     display_alert(STR_ERROR_ALERT_TITLE, STR_GUI_ERROR_PREFIX, STR_QUIT_BUTTON, text);
1773     #else
1774     printf(GetString(STR_SHELL_ERROR_PREFIX), text);
1775     #endif
1776     }
1777    
1778    
1779     /*
1780     * Display warning alert
1781     */
1782    
1783     void WarningAlert(const char *text)
1784     {
1785     #ifdef ENABLE_GTK
1786     if (PrefsFindBool("nogui") || x_display == NULL) {
1787     printf(GetString(STR_SHELL_WARNING_PREFIX), text);
1788     return;
1789     }
1790     display_alert(STR_WARNING_ALERT_TITLE, STR_GUI_WARNING_PREFIX, STR_OK_BUTTON, text);
1791     #else
1792     printf(GetString(STR_SHELL_WARNING_PREFIX), text);
1793     #endif
1794     }
1795    
1796    
1797     /*
1798     * Display choice alert
1799     */
1800    
1801     bool ChoiceAlert(const char *text, const char *pos, const char *neg)
1802     {
1803     printf(GetString(STR_SHELL_WARNING_PREFIX), text);
1804     return false; //!!
1805     }