ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/main_unix.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/main_unix.cpp (file contents):
Revision 1.16 by cebix, 2000-07-22T18:12:34Z vs.
Revision 1.81 by cebix, 2010-02-21T12:00:25Z

# Line 1 | Line 1
1   /*
2   *  main_unix.cpp - Startup code for Unix
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) Christian Bauer
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
# Line 24 | Line 24
24   #include <stdlib.h>
25   #include <signal.h>
26   #include <errno.h>
27 < #include <X11/Xlib.h>
27 >
28 > #ifdef USE_SDL
29 > # include <SDL.h>
30 > #endif
31 >
32 > #ifndef USE_SDL_VIDEO
33 > # include <X11/Xlib.h>
34 > #endif
35  
36   #ifdef HAVE_PTHREADS
37   # include <pthread.h>
38   #endif
39  
40 < #if defined(USE_MAPPED_MEMORY) || REAL_ADDRESSING
40 > #if REAL_ADDRESSING || DIRECT_ADDRESSING
41   # include <sys/mman.h>
42   #endif
43  
# Line 50 | Line 57 | struct sigstate {
57  
58   #ifdef ENABLE_GTK
59   # include <gtk/gtk.h>
60 + # include <gdk/gdk.h>
61 + # ifdef HAVE_GNOMEUI
62 + #  include <gnome.h>
63 + # endif
64   #endif
65  
66   #ifdef ENABLE_XF86_DGA
67   # include <X11/Xutil.h>
68 < # include <X11/extensions/xf86dga.h>
68 > # include <X11/extensions/Xxf86dga.h>
69   #endif
70  
71 + #include <string>
72 + using std::string;
73 +
74   #include "cpu_emulation.h"
75   #include "sys.h"
76   #include "rom_patches.h"
# Line 70 | Line 84 | struct sigstate {
84   #include "user_strings.h"
85   #include "version.h"
86   #include "main.h"
87 + #include "vm_alloc.h"
88 + #include "sigsegv.h"
89 + #include "rpc.h"
90 +
91 + #if USE_JIT
92 + extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp
93 + #endif
94  
95   #ifdef ENABLE_MON
96   # include "mon.h"
# Line 81 | Line 102 | struct sigstate {
102  
103   // Constants
104   const char ROM_FILE_NAME[] = "ROM";
105 + #if !EMULATED_68K
106   const int SIG_STACK_SIZE = SIGSTKSZ;    // Size of signal stack
107 + #endif
108   const int SCRATCH_MEM_SIZE = 0x10000;   // Size of scratch memory area
109  
110  
# Line 104 | Line 127 | bool TwentyFourBitAddressing;
127  
128  
129   // Global variables
130 < char *x_display_name = NULL;                                            // X11 display name
131 < Display *x_display = NULL;                                                      // X11 display handle
130 > #ifndef USE_SDL_VIDEO
131 > extern char *x_display_name;                                            // X11 display name
132 > extern Display *x_display;                                                      // X11 display handle
133 > #ifdef X11_LOCK_TYPE
134 > X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT;           // X11 display lock
135 > #endif
136 > #endif
137  
138 < static int zero_fd = -1;                                                        // FD of /dev/zero
111 < static uint8 last_xpram[256];                                           // Buffer for monitoring XPRAM changes
138 > static uint8 last_xpram[XPRAM_SIZE];                            // Buffer for monitoring XPRAM changes
139  
140   #ifdef HAVE_PTHREADS
141 + #if !EMULATED_68K
142   static pthread_t emul_thread;                                           // Handle of MacOS emulation thread (main thread)
143 + #endif
144  
145   static bool xpram_thread_active = false;                        // Flag: XPRAM watchdog installed
146   static volatile bool xpram_thread_cancel = false;       // Flag: Cancel XPRAM thread
# Line 122 | Line 151 | static volatile bool tick_thread_cancel
151   static pthread_t tick_thread;                                           // 60Hz thread
152   static pthread_attr_t tick_thread_attr;                         // 60Hz thread attributes
153  
125 #if EMULATED_68K
154   static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER;        // Mutex to protect InterruptFlags
155 < #endif
155 > #define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock)
156 > #define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock)
157 >
158 > #else
159 >
160 > #define LOCK_INTFLAGS
161 > #define UNLOCK_INTFLAGS
162 >
163   #endif
164  
165   #if !EMULATED_68K
# Line 133 | Line 168 | static struct sigaction sigirq_sa;     // Vi
168   static struct sigaction sigill_sa;      // Illegal instruction
169   static void *sig_stack = NULL;          // Stack for signal handlers
170   uint16 EmulatedSR;                                      // Emulated bits of SR (supervisor bit and interrupt mask)
136 uint32 ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
171   #endif
172  
173 + #if USE_SCRATCHMEM_SUBTERFUGE
174 + uint8 *ScratchMem = NULL;                       // Scratch memory for Mac ROM writes
175 + #endif
176 +
177 + #if !defined(HAVE_PTHREADS)
178   static struct sigaction timer_sa;       // sigaction used for timer
179  
180   #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
181   #define SIG_TIMER SIGRTMIN
182   static timer_t timer;                           // 60Hz timer
183   #endif
184 + #endif // !HAVE_PTHREADS
185  
186   #ifdef ENABLE_MON
187   static struct sigaction sigint_sa;      // sigaction for SIGINT handler
# Line 152 | Line 192 | static void sigint_handler(...);
192   static bool lm_area_mapped = false;     // Flag: Low Memory area mmap()ped
193   #endif
194  
195 < #ifdef USE_MAPPED_MEMORY
196 < extern char *address_space, *good_address_map;
157 < #endif
195 > static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI
196 > static const char *gui_connection_path = NULL;  // GUI connection identifier
197  
198  
199   // Prototypes
# Line 187 | Line 226 | char *strdup(const char *s)
226  
227  
228   /*
229 + *  Helpers to map memory that can be accessed from the Mac side
230 + */
231 +
232 + // NOTE: VM_MAP_32BIT is only used when compiling a 64-bit JIT on specific platforms
233 + void *vm_acquire_mac(size_t size)
234 + {
235 +        return vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT);
236 + }
237 +
238 + static int vm_acquire_mac_fixed(void *addr, size_t size)
239 + {
240 +        return vm_acquire_fixed(addr, size, VM_MAP_DEFAULT | VM_MAP_32BIT);
241 + }
242 +
243 +
244 + /*
245 + *  SIGSEGV handler
246 + */
247 +
248 + static sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip)
249 + {
250 +        const uintptr fault_address = (uintptr)sigsegv_get_fault_address(sip);
251 + #if ENABLE_VOSF
252 +        // Handle screen fault
253 +        extern bool Screen_fault_handler(sigsegv_info_t *sip);
254 +        if (Screen_fault_handler(sip))
255 +                return SIGSEGV_RETURN_SUCCESS;
256 + #endif
257 +
258 + #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
259 +        // Ignore writes to ROM
260 +        if (((uintptr)fault_address - (uintptr)ROMBaseHost) < ROMSize)
261 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
262 +
263 +        // Ignore all other faults, if requested
264 +        if (PrefsFindBool("ignoresegv"))
265 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
266 + #endif
267 +
268 +        return SIGSEGV_RETURN_FAILURE;
269 + }
270 +
271 + /*
272 + *  Dump state when everything went wrong after a SEGV
273 + */
274 +
275 + static void sigsegv_dump_state(sigsegv_info_t *sip)
276 + {
277 +        const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip);
278 +        const sigsegv_address_t fault_instruction = sigsegv_get_fault_instruction_address(sip);
279 +        fprintf(stderr, "Caught SIGSEGV at address %p", fault_address);
280 +        if (fault_instruction != SIGSEGV_INVALID_ADDRESS)
281 +                fprintf(stderr, " [IP=%p]", fault_instruction);
282 +        fprintf(stderr, "\n");
283 + #if EMULATED_68K
284 +        uaecptr nextpc;
285 +        extern void m68k_dumpstate(uaecptr *nextpc);
286 +        m68k_dumpstate(&nextpc);
287 + #endif
288 + #if USE_JIT && JIT_DEBUG
289 +        extern void compiler_dumpstate(void);
290 +        compiler_dumpstate();
291 + #endif
292 +        VideoQuitFullScreen();
293 + #ifdef ENABLE_MON
294 +        const char *arg[4] = {"mon", "-m", "-r", NULL};
295 +        mon(3, arg);
296 + #endif
297 +        QuitEmulator();
298 + }
299 +
300 +
301 + /*
302 + *  Update virtual clock and trigger interrupts if necessary
303 + */
304 +
305 + #ifdef USE_CPU_EMUL_SERVICES
306 + static uint64 n_check_ticks = 0;
307 + static uint64 emulated_ticks_start = 0;
308 + static uint64 emulated_ticks_count = 0;
309 + static int64 emulated_ticks_current = 0;
310 + static int32 emulated_ticks_quantum = 1000;
311 + int32 emulated_ticks = emulated_ticks_quantum;
312 +
313 + void cpu_do_check_ticks(void)
314 + {
315 + #if DEBUG
316 +        n_check_ticks++;
317 + #endif
318 +
319 +        uint64 now;
320 +        static uint64 next = 0;
321 +        if (next == 0)
322 +                next = emulated_ticks_start = GetTicks_usec();
323 +
324 +        // Update total instructions count
325 +        if (emulated_ticks <= 0) {
326 +                emulated_ticks_current += (emulated_ticks_quantum - emulated_ticks);
327 +                // XXX: can you really have a machine fast enough to overflow
328 +                // a 63-bit m68k instruction counter within 16 ms?
329 +                if (emulated_ticks_current < 0) {
330 +                        printf("WARNING: Overflowed 63-bit m68k instruction counter in less than 16 ms!\n");
331 +                        goto recalibrate_quantum;
332 +                }
333 +        }
334 +
335 +        // Check for interrupt opportunity
336 +        now = GetTicks_usec();
337 +        if (next < now) {
338 +                one_tick();
339 +                do {
340 +                        next += 16625;
341 +                } while (next < now);
342 +                emulated_ticks_count++;
343 +
344 +                // Recalibrate 1000 Hz quantum every 10 ticks
345 +                static uint64 last = 0;
346 +                if (last == 0)
347 +                        last = now;
348 +                else if (now - last > 166250) {
349 +                  recalibrate_quantum:
350 +                        emulated_ticks_quantum = ((uint64)emulated_ticks_current * 1000) / (now - last);
351 +                        emulated_ticks_current = 0;
352 +                        last = now;
353 +                }
354 +        }
355 +
356 +        // Update countdown
357 +        if (emulated_ticks <= 0)
358 +                emulated_ticks += emulated_ticks_quantum;
359 + }
360 + #endif
361 +
362 +
363 + /*
364   *  Main program
365   */
366  
367 + static void usage(const char *prg_name)
368 + {
369 +        printf(
370 +                "Usage: %s [OPTION...]\n"
371 +                "\nUnix options:\n"
372 +                "  --config FILE\n    read/write configuration from/to FILE\n"
373 +                "  --display STRING\n    X display to use\n"
374 +                "  --break ADDRESS\n    set ROM breakpoint\n"
375 +                "  --rominfo\n    dump ROM information\n", prg_name
376 +        );
377 +        LoadPrefs(NULL); // read the prefs file so PrefsPrintUsage() will print the correct default values
378 +        PrefsPrintUsage();
379 +        exit(0);
380 + }
381 +
382   int main(int argc, char **argv)
383   {
384 +        const char *vmdir = NULL;
385          char str[256];
386  
387          // Initialize variables
# Line 204 | Line 394 | int main(int argc, char **argv)
394          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
395          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
396  
397 <        // Parse arguments
397 >        // Parse command line arguments
398          for (int i=1; i<argc; i++) {
399 <                if (strcmp(argv[i], "-display") == 0 && ++i < argc)
400 <                        x_display_name = argv[i];
401 <                else if (strcmp(argv[i], "-break") == 0 && ++i < argc)
402 <                        ROMBreakpoint = strtol(argv[i], NULL, 0);
403 <                else if (strcmp(argv[i], "-rominfo") == 0)
399 >                if (strcmp(argv[i], "--help") == 0) {
400 >                        usage(argv[0]);
401 > #ifndef USE_SDL_VIDEO
402 >                } else if (strcmp(argv[i], "--display") == 0) {
403 >                        i++; // don't remove the argument, gtk_init() needs it too
404 >                        if (i < argc)
405 >                                x_display_name = strdup(argv[i]);
406 > #endif
407 >                } else if (strcmp(argv[i], "--gui-connection") == 0) {
408 >                        argv[i++] = NULL;
409 >                        if (i < argc) {
410 >                                gui_connection_path = argv[i];
411 >                                argv[i] = NULL;
412 >                        }
413 >                } else if (strcmp(argv[i], "--break") == 0) {
414 >                        argv[i++] = NULL;
415 >                        if (i < argc) {
416 >                                ROMBreakpoint = strtol(argv[i], NULL, 0);
417 >                                argv[i] = NULL;
418 >                        }
419 >                } else if (strcmp(argv[i], "--config") == 0) {
420 >                        argv[i++] = NULL;
421 >                        if (i < argc) {
422 >                                extern string UserPrefsPath; // from prefs_unix.cpp
423 >                                UserPrefsPath = argv[i];
424 >                                argv[i] = NULL;
425 >                        }
426 >                } else if (strcmp(argv[i], "--rominfo") == 0) {
427 >                        argv[i] = NULL;
428                          PrintROMInfo = true;
429 +                }
430          }
431  
432 +        // Remove processed arguments
433 +        for (int i=1; i<argc; i++) {
434 +                int k;
435 +                for (k=i; k<argc; k++)
436 +                        if (argv[k] != NULL)
437 +                                break;
438 +                if (k > i) {
439 +                        k -= i;
440 +                        for (int j=i+k; j<argc; j++)
441 +                                argv[j-k] = argv[j];
442 +                        argc -= k;
443 +                }
444 +        }
445 +
446 +        // Connect to the external GUI
447 +        if (gui_connection_path) {
448 +                if ((gui_connection = rpc_init_client(gui_connection_path)) == NULL) {
449 +                        fprintf(stderr, "Failed to initialize RPC client connection to the GUI\n");
450 +                        return 1;
451 +                }
452 +        }
453 +
454 + #ifdef ENABLE_GTK
455 +        if (!gui_connection) {
456 + #ifdef HAVE_GNOMEUI
457 +                // Init GNOME/GTK
458 +                char version[16];
459 +                sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
460 +                gnome_init("Basilisk II", version, argc, argv);
461 + #else
462 +                // Init GTK
463 +                gtk_set_locale();
464 +                gtk_init(&argc, &argv);
465 + #endif
466 +        }
467 + #endif
468 +
469 +        // Read preferences
470 +        PrefsInit(vmdir, argc, argv);
471 +
472 +        // Any command line arguments left?
473 +        for (int i=1; i<argc; i++) {
474 +                if (argv[i][0] == '-') {
475 +                        fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
476 +                        usage(argv[0]);
477 +                }
478 +        }
479 +
480 + #ifndef USE_SDL_VIDEO
481          // Open display
482          x_display = XOpenDisplay(x_display_name);
483          if (x_display == NULL) {
# Line 227 | Line 491 | int main(int argc, char **argv)
491          // Fork out, so we can return from fullscreen mode when things get ugly
492          XF86DGAForkApp(DefaultScreen(x_display));
493   #endif
230
231 #ifdef ENABLE_GTK
232        // Init GTK
233        gtk_set_locale();
234        gtk_init(&argc, &argv);
494   #endif
495  
496 <        // Read preferences
497 <        PrefsInit();
496 > #ifdef USE_SDL
497 >        // Initialize SDL system
498 >        int sdl_flags = 0;
499 > #ifdef USE_SDL_VIDEO
500 >        sdl_flags |= SDL_INIT_VIDEO;
501 > #endif
502 > #ifdef USE_SDL_AUDIO
503 >        sdl_flags |= SDL_INIT_AUDIO;
504 > #endif
505 >        assert(sdl_flags != 0);
506 >        if (SDL_Init(sdl_flags) == -1) {
507 >                char str[256];
508 >                sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError());
509 >                ErrorAlert(str);
510 >                QuitEmulator();
511 >        }
512 >        atexit(SDL_Quit);
513 > #endif
514  
515          // Init system routines
516          SysInit();
517  
518          // Show preferences editor
519 <        if (!PrefsFindBool("nogui"))
519 >        if (!gui_connection && !PrefsFindBool("nogui"))
520                  if (!PrefsEditor())
521                          QuitEmulator();
522  
523 <        // Open /dev/zero
524 <        zero_fd = open("/dev/zero", O_RDWR);
525 <        if (zero_fd < 0) {
251 <                sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
523 >        // Install the handler for SIGSEGV
524 >        if (!sigsegv_install_handler(sigsegv_handler)) {
525 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
526                  ErrorAlert(str);
527                  QuitEmulator();
528          }
529 +        
530 +        // Register dump state function when we got mad after a segfault
531 +        sigsegv_set_dump_state(sigsegv_dump_state);
532  
533          // Read RAM size
534          RAMSize = PrefsFindInt32("ramsize") & 0xfff00000;       // Round down to 1MB boundary
# Line 259 | Line 536 | int main(int argc, char **argv)
536                  WarningAlert(GetString(STR_SMALL_RAM_WARN));
537                  RAMSize = 1024*1024;
538          }
539 +        if (RAMSize > 1023*1024*1024)                                           // Cap to 1023MB (APD crashes at 1GB)
540 +                RAMSize = 1023*1024*1024;
541 +
542 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
543 +        RAMSize = RAMSize & -getpagesize();                                     // Round down to page boundary
544 + #endif
545 +        
546 +        // Initialize VM system
547 +        vm_init();
548  
549   #if REAL_ADDRESSING
550 <        // Create Low Memory area (0x0000..0x2000)
551 <        if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
550 >        // Flag: RAM and ROM are contigously allocated from address 0
551 >        bool memory_mapped_from_zero = false;
552 >
553 >        // Make sure to map RAM & ROM at address 0 only on platforms that
554 >        // supports linker scripts to relocate the Basilisk II executable
555 >        // above 0x70000000
556 > #if HAVE_LINKER_SCRIPT
557 >        const bool can_map_all_memory = true;
558 > #else
559 >        const bool can_map_all_memory = false;
560 > #endif
561 >        
562 >        // Try to allocate all memory from 0x0000, if it is not known to crash
563 >        if (can_map_all_memory && (vm_acquire_mac_fixed(0, RAMSize + 0x100000) == 0)) {
564 >                D(bug("Could allocate RAM and ROM from 0x0000\n"));
565 >                memory_mapped_from_zero = true;
566 >        }
567 >        
568 > #ifndef PAGEZERO_HACK
569 >        // Otherwise, just create the Low Memory area (0x0000..0x2000)
570 >        else if (vm_acquire_mac_fixed(0, 0x2000) == 0) {
571 >                D(bug("Could allocate the Low Memory globals\n"));
572 >                lm_area_mapped = true;
573 >        }
574 >        
575 >        // Exit on failure
576 >        else {
577                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
578                  ErrorAlert(str);
579                  QuitEmulator();
580          }
270        lm_area_mapped = true;
581   #endif
582 + #endif /* REAL_ADDRESSING */
583  
584 < #if !EMULATED_68K
584 >        // Create areas for Mac RAM and ROM
585 > #if REAL_ADDRESSING
586 >        if (memory_mapped_from_zero) {
587 >                RAMBaseHost = (uint8 *)0;
588 >                ROMBaseHost = RAMBaseHost + RAMSize;
589 >        }
590 >        else
591 > #endif
592 >        {
593 >                uint8 *ram_rom_area = (uint8 *)vm_acquire_mac(RAMSize + 0x100000);
594 >                if (ram_rom_area == VM_MAP_FAILED) {    
595 >                        ErrorAlert(STR_NO_MEM_ERR);
596 >                        QuitEmulator();
597 >                }
598 >                RAMBaseHost = ram_rom_area;
599 >                ROMBaseHost = RAMBaseHost + RAMSize;
600 >        }
601 >
602 > #if USE_SCRATCHMEM_SUBTERFUGE
603          // Allocate scratch memory
604 <        ScratchMem = (uint32)malloc(SCRATCH_MEM_SIZE);
605 <        if (ScratchMem == NULL) {
606 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
604 >        ScratchMem = (uint8 *)vm_acquire_mac(SCRATCH_MEM_SIZE);
605 >        if (ScratchMem == VM_MAP_FAILED) {
606 >                ErrorAlert(STR_NO_MEM_ERR);
607                  QuitEmulator();
608          }
609          ScratchMem += SCRATCH_MEM_SIZE/2;       // ScratchMem points to middle of block
610   #endif
611  
612 <        // Create areas for Mac RAM and ROM
613 < #if defined(USE_MAPPED_MEMORY)
614 <    good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, zero_fd, 0);
615 <    address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
616 <    if ((int)address_space < 0 || (int)good_address_map < 0) {
288 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
289 <                QuitEmulator();
290 <    }
291 <    RAMBaseHost = (uint8 *)mmap(address_space, RAMSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
292 <    ROMBaseHost = (uint8 *)mmap(address_space + 0x00400000, 0x80000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
293 <        char *nam = tmpnam(NULL);
294 <    int good_address_fd = open(nam, O_CREAT | O_RDWR, 0600);
295 <        char buffer[4096];
296 <    memset(buffer, 1, sizeof(buffer));
297 <    write(good_address_fd, buffer, sizeof(buffer));
298 <    unlink(nam);
299 <    for (int i=0; i<RAMSize; i+=4096)
300 <        mmap(good_address_map + i, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
301 <    for (int i=0; i<0x80000; i+=4096)
302 <        mmap(good_address_map + i + 0x00400000, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
303 < #else
304 <        RAMBaseHost = new uint8[RAMSize];
305 <        ROMBaseHost = new uint8[0x100000];
612 > #if DIRECT_ADDRESSING
613 >        // RAMBaseMac shall always be zero
614 >        MEMBaseDiff = (uintptr)RAMBaseHost;
615 >        RAMBaseMac = 0;
616 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
617   #endif
618 < #if REAL_ADDRESSING && !EMULATED_68K
619 <        RAMBaseMac = (uint32)RAMBaseHost;
620 <        ROMBaseMac = (uint32)ROMBaseHost;
618 > #if REAL_ADDRESSING
619 >        RAMBaseMac = Host2MacAddr(RAMBaseHost);
620 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
621   #endif
622          D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
623          D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
624 <
624 >        
625          // Get rom file path from preferences
626          const char *rom_path = PrefsFindString("rom");
627  
628          // Load Mac ROM
629          int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
630          if (rom_fd < 0) {
631 <                ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
631 >                ErrorAlert(STR_NO_ROM_FILE_ERR);
632                  QuitEmulator();
633          }
634          printf(GetString(STR_READING_ROM_FILE));
635          ROMSize = lseek(rom_fd, 0, SEEK_END);
636          if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
637 <                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
637 >                ErrorAlert(STR_ROM_SIZE_ERR);
638                  close(rom_fd);
639                  QuitEmulator();
640          }
641          lseek(rom_fd, 0, SEEK_SET);
642          if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) {
643 <                ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
643 >                ErrorAlert(STR_ROM_FILE_READ_ERR);
644                  close(rom_fd);
645                  QuitEmulator();
646          }
# Line 359 | Line 670 | int main(int argc, char **argv)
670                  printf("WARNING: Cannot detect CPU type, assuming 68020\n");
671                  CPUType = 2;
672          }
673 <        FPUType = 0;    //!!
673 >        FPUType = 1;    // NetBSD has an FPU emulation, so the FPU ought to be available at all times
674          TwentyFourBitAddressing = false;
675   #endif
676  
677          // Initialize everything
678 <        if (!InitAll())
678 >        if (!InitAll(vmdir))
679                  QuitEmulator();
680          D(bug("Initialization complete\n"));
681  
682 + #if !EMULATED_68K
683 +        // (Virtual) supervisor mode, disable interrupts
684 +        EmulatedSR = 0x2700;
685 +
686   #ifdef HAVE_PTHREADS
687          // Get handle of main thread
688          emul_thread = pthread_self();
689   #endif
690  
376 #if !EMULATED_68K
377        // (Virtual) supervisor mode, disable interrupts
378        EmulatedSR = 0x2700;
379
691          // Create and install stack for signal handlers
692          sig_stack = malloc(SIG_STACK_SIZE);
693          D(bug("Signal stack at %p\n", sig_stack));
694          if (sig_stack == NULL) {
695 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
695 >                ErrorAlert(STR_NOT_ENOUGH_MEMORY_ERR);
696                  QuitEmulator();
697          }
698          stack_t new_stack;
# Line 422 | Line 733 | int main(int argc, char **argv)
733   #ifdef ENABLE_MON
734          // Setup SIGINT handler to enter mon
735          sigemptyset(&sigint_sa.sa_mask);
736 <        sigint_sa.sa_handler = sigint_handler;
736 >        sigint_sa.sa_handler = (void (*)(int))sigint_handler;
737          sigint_sa.sa_flags = 0;
738          sigaction(SIGINT, &sigint_sa, NULL);
739   #endif
740  
741 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
741 > #ifndef USE_CPU_EMUL_SERVICES
742 > #if defined(HAVE_PTHREADS)
743 >
744 >        // POSIX threads available, start 60Hz thread
745 >        Set_pthread_attr(&tick_thread_attr, 0);
746 >        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
747 >        if (!tick_thread_active) {
748 >                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
749 >                ErrorAlert(str);
750 >                QuitEmulator();
751 >        }
752 >        D(bug("60Hz thread started\n"));
753 >
754 > #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
755  
756          // POSIX.4 timers and real-time signals available, start 60Hz timer
757          sigemptyset(&timer_sa.sa_mask);
758 <        timer_sa.sa_sigaction = one_tick;
758 >        timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick;
759          timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
760          if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
761                  sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
# Line 458 | Line 782 | int main(int argc, char **argv)
782          }
783          D(bug("60Hz timer started\n"));
784  
461 #elif defined(HAVE_PTHREADS)
462
463        // POSIX threads available, start 60Hz thread
464        pthread_attr_init(&tick_thread_attr);
465 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
466        if (geteuid() == 0) {
467                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
468                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
469                struct sched_param fifo_param;
470                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
471                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
472        }
473 #endif
474        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
475        if (!tick_thread_active) {
476                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
477                ErrorAlert(str);
478                QuitEmulator();
479        }
480        D(bug("60Hz thread started\n"));
481
785   #else
786  
787          // Start 60Hz timer
788          sigemptyset(&timer_sa.sa_mask);         // Block virtual 68k interrupts during SIGARLM handling
789 + #if !EMULATED_68K
790          sigaddset(&timer_sa.sa_mask, SIG_IRQ);
791 + #endif
792          timer_sa.sa_handler = one_tick;
793          timer_sa.sa_flags = SA_ONSTACK | SA_RESTART;
794          if (sigaction(SIGALRM, &timer_sa, NULL) < 0) {
# Line 497 | Line 802 | int main(int argc, char **argv)
802          setitimer(ITIMER_REAL, &req, NULL);
803  
804   #endif
805 + #endif
806  
807 < #ifdef HAVE_PTHREADS
807 > #ifdef USE_PTHREADS_SERVICES
808          // Start XPRAM watchdog thread
809 <        memcpy(last_xpram, XPRAM, 256);
809 >        memcpy(last_xpram, XPRAM, XPRAM_SIZE);
810          xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
811          D(bug("XPRAM thread started\n"));
812   #endif
# Line 527 | Line 833 | void QuitEmulator(void)
833          Exit680x0();
834   #endif
835  
836 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
837 <        // Stop 60Hz timer
838 <        timer_delete(timer);
839 < #elif defined(HAVE_PTHREADS)
836 > #if defined(USE_CPU_EMUL_SERVICES)
837 >        // Show statistics
838 >        uint64 emulated_ticks_end = GetTicks_usec();
839 >        D(bug("%ld ticks in %ld usec = %f ticks/sec [%ld tick checks]\n",
840 >                  (long)emulated_ticks_count, (long)(emulated_ticks_end - emulated_ticks_start),
841 >                  emulated_ticks_count * 1000000.0 / (emulated_ticks_end - emulated_ticks_start), (long)n_check_ticks));
842 > #elif defined(USE_PTHREADS_SERVICES)
843          // Stop 60Hz thread
844          if (tick_thread_active) {
845                  tick_thread_cancel = true;
# Line 539 | Line 848 | void QuitEmulator(void)
848   #endif
849                  pthread_join(tick_thread, NULL);
850          }
851 + #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
852 +        // Stop 60Hz timer
853 +        timer_delete(timer);
854   #else
855          struct itimerval req;
856          req.it_interval.tv_sec = req.it_value.tv_sec = 0;
# Line 546 | Line 858 | void QuitEmulator(void)
858          setitimer(ITIMER_REAL, &req, NULL);
859   #endif
860  
861 < #ifdef HAVE_PTHREADS
861 > #ifdef USE_PTHREADS_SERVICES
862          // Stop XPRAM watchdog thread
863          if (xpram_thread_active) {
864                  xpram_thread_cancel = true;
# Line 560 | Line 872 | void QuitEmulator(void)
872          // Deinitialize everything
873          ExitAll();
874  
875 <        // Delete ROM area
876 <        delete[] ROMBaseHost;
877 <
878 <        // Delete RAM area
879 <        delete[] RAMBaseHost;
875 >        // Free ROM/RAM areas
876 >        if (RAMBaseHost != VM_MAP_FAILED) {
877 >                vm_release(RAMBaseHost, RAMSize + 0x100000);
878 >                RAMBaseHost = NULL;
879 >                ROMBaseHost = NULL;
880 >        }
881  
882 < #if !EMULATED_68K
882 > #if USE_SCRATCHMEM_SUBTERFUGE
883          // Delete scratch memory area
884 <        if (ScratchMem)
885 <                free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
884 >        if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
885 >                vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
886 >                ScratchMem = NULL;
887 >        }
888   #endif
889  
890   #if REAL_ADDRESSING
891          // Delete Low Memory area
892          if (lm_area_mapped)
893 <                munmap((char *)0x0000, 0x2000);
893 >                vm_release(0, 0x2000);
894   #endif
895 <
896 <        // Close /dev/zero
897 <        if (zero_fd > 0)
583 <                close(zero_fd);
895 >        
896 >        // Exit VM wrappers
897 >        vm_exit();
898  
899          // Exit system routines
900          SysExit();
# Line 589 | Line 903 | void QuitEmulator(void)
903          PrefsExit();
904  
905          // Close X11 server connection
906 + #ifndef USE_SDL_VIDEO
907          if (x_display)
908                  XCloseDisplay(x_display);
909 + #endif
910 +
911 +        // Notify GUI we are about to leave
912 +        if (gui_connection) {
913 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
914 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID);
915 +        }
916  
917          exit(0);
918   }
# Line 603 | Line 925 | void QuitEmulator(void)
925  
926   void FlushCodeCache(void *start, uint32 size)
927   {
928 + #if USE_JIT
929 +    if (UseJIT)
930 +                flush_icache_range((uint8 *)start, size);
931 + #endif
932   #if !EMULATED_68K && defined(__NetBSD__)
933          m68k_sync_icache(start, size);
934   #endif
# Line 620 | Line 946 | static void sigint_handler(...)
946          uaecptr nextpc;
947          extern void m68k_dumpstate(uaecptr *nextpc);
948          m68k_dumpstate(&nextpc);
949 < #else
950 <        char *arg[2] = {"rmon", NULL};
951 <        mon(1, arg);
949 > #endif
950 >        VideoQuitFullScreen();
951 >        const char *arg[4] = {"mon", "-m", "-r", NULL};
952 >        mon(3, arg);
953          QuitEmulator();
954 + }
955 + #endif
956 +
957 +
958 + #ifdef HAVE_PTHREADS
959 + /*
960 + *  Pthread configuration
961 + */
962 +
963 + void Set_pthread_attr(pthread_attr_t *attr, int priority)
964 + {
965 +        pthread_attr_init(attr);
966 + #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
967 +        // Some of these only work for superuser
968 +        if (geteuid() == 0) {
969 +                pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
970 +                pthread_attr_setschedpolicy(attr, SCHED_FIFO);
971 +                struct sched_param fifo_param;
972 +                fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
973 +                                              sched_get_priority_max(SCHED_FIFO)) / 2 +
974 +                                             priority);
975 +                pthread_attr_setschedparam(attr, &fifo_param);
976 +        }
977 +        if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
978 + #ifdef PTHREAD_SCOPE_BOUND_NP
979 +            // If system scope is not available (eg. we're not running
980 +            // with CAP_SCHED_MGT capability on an SGI box), try bound
981 +            // scope.  It exposes pthread scheduling to the kernel,
982 +            // without setting realtime priority.
983 +            pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
984 + #endif
985 +        }
986   #endif
987   }
988 + #endif // HAVE_PTHREADS
989 +
990 +
991 + /*
992 + *  Mutexes
993 + */
994 +
995 + #ifdef HAVE_PTHREADS
996 +
997 + struct B2_mutex {
998 +        B2_mutex() {
999 +            pthread_mutexattr_t attr;
1000 +            pthread_mutexattr_init(&attr);
1001 +            // Initialize the mutex for priority inheritance --
1002 +            // required for accurate timing.
1003 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__)
1004 +            pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
1005 + #endif
1006 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
1007 +            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
1008 + #endif
1009 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
1010 +            pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
1011 + #endif
1012 +            pthread_mutex_init(&m, &attr);
1013 +            pthread_mutexattr_destroy(&attr);
1014 +        }
1015 +        ~B2_mutex() {
1016 +            pthread_mutex_trylock(&m); // Make sure it's locked before
1017 +            pthread_mutex_unlock(&m);  // unlocking it.
1018 +            pthread_mutex_destroy(&m);
1019 +        }
1020 +        pthread_mutex_t m;
1021 + };
1022 +
1023 + B2_mutex *B2_create_mutex(void)
1024 + {
1025 +        return new B2_mutex;
1026 + }
1027 +
1028 + void B2_lock_mutex(B2_mutex *mutex)
1029 + {
1030 +        pthread_mutex_lock(&mutex->m);
1031 + }
1032 +
1033 + void B2_unlock_mutex(B2_mutex *mutex)
1034 + {
1035 +        pthread_mutex_unlock(&mutex->m);
1036 + }
1037 +
1038 + void B2_delete_mutex(B2_mutex *mutex)
1039 + {
1040 +        delete mutex;
1041 + }
1042 +
1043 + #else
1044 +
1045 + struct B2_mutex {
1046 +        int dummy;
1047 + };
1048 +
1049 + B2_mutex *B2_create_mutex(void)
1050 + {
1051 +        return new B2_mutex;
1052 + }
1053 +
1054 + void B2_lock_mutex(B2_mutex *mutex)
1055 + {
1056 + }
1057 +
1058 + void B2_unlock_mutex(B2_mutex *mutex)
1059 + {
1060 + }
1061 +
1062 + void B2_delete_mutex(B2_mutex *mutex)
1063 + {
1064 +        delete mutex;
1065 + }
1066 +
1067   #endif
1068  
1069  
# Line 638 | Line 1076 | uint32 InterruptFlags = 0;
1076   #if EMULATED_68K
1077   void SetInterruptFlag(uint32 flag)
1078   {
1079 < #ifdef HAVE_PTHREADS
642 <        pthread_mutex_lock(&intflag_lock);
1079 >        LOCK_INTFLAGS;
1080          InterruptFlags |= flag;
1081 <        pthread_mutex_unlock(&intflag_lock);
645 < #else
646 <        InterruptFlags |= flag;         // Pray that this is an atomic operation...
647 < #endif
1081 >        UNLOCK_INTFLAGS;
1082   }
1083  
1084   void ClearInterruptFlag(uint32 flag)
1085   {
1086 < #ifdef HAVE_PTHREADS
653 <        pthread_mutex_lock(&intflag_lock);
1086 >        LOCK_INTFLAGS;
1087          InterruptFlags &= ~flag;
1088 <        pthread_mutex_unlock(&intflag_lock);
656 < #else
657 <        InterruptFlags &= ~flag;
658 < #endif
1088 >        UNLOCK_INTFLAGS;
1089   }
1090   #endif
1091  
# Line 668 | Line 1098 | void TriggerInterrupt(void)
1098          raise(SIG_IRQ);
1099   #endif
1100   }
1101 +
1102 + void TriggerNMI(void)
1103 + {
1104 +        // not yet supported
1105 + }
1106   #endif
1107  
1108  
# Line 677 | Line 1112 | void TriggerInterrupt(void)
1112  
1113   static void xpram_watchdog(void)
1114   {
1115 <        if (memcmp(last_xpram, XPRAM, 256)) {
1116 <                memcpy(last_xpram, XPRAM, 256);
1115 >        if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
1116 >                memcpy(last_xpram, XPRAM, XPRAM_SIZE);
1117                  SaveXPRAM();
1118          }
1119   }
1120  
1121 < #ifdef HAVE_PTHREADS
1121 > #ifdef USE_PTHREADS_SERVICES
1122   static void *xpram_func(void *arg)
1123   {
1124          while (!xpram_thread_cancel) {
1125                  for (int i=0; i<60 && !xpram_thread_cancel; i++)
1126 <                        Delay_usec(1000000);
1126 >                        Delay_usec(999999);             // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true
1127                  xpram_watchdog();
1128          }
1129          return NULL;
# Line 705 | Line 1140 | static void one_second(void)
1140          // Pseudo Mac 1Hz interrupt, update local time
1141          WriteMacInt32(0x20c, TimerDateTime());
1142  
1143 <        SetInterruptFlag(INTFLAG_60HZ);
1143 >        SetInterruptFlag(INTFLAG_1HZ);
1144          TriggerInterrupt();
1145  
1146 < #ifndef HAVE_PTHREADS
1146 > #ifndef USE_PTHREADS_SERVICES
1147          static int second_counter = 0;
1148          if (++second_counter > 60) {
1149                  second_counter = 0;
# Line 725 | Line 1160 | static void one_tick(...)
1160                  one_second();
1161          }
1162  
1163 < #ifndef HAVE_PTHREADS
1164 <        // No threads available, perform video refresh from here
1163 > #ifndef USE_PTHREADS_SERVICES
1164 >        // Threads not used to trigger interrupts, perform video refresh from here
1165          VideoRefresh();
1166   #endif
1167  
1168 + #ifndef HAVE_PTHREADS
1169 +        // No threads available, perform networking from here
1170 +        SetInterruptFlag(INTFLAG_ETHER);
1171 + #endif
1172 +
1173          // Trigger 60Hz interrupt
1174          if (ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted()) {
1175                  SetInterruptFlag(INTFLAG_60HZ);
# Line 737 | Line 1177 | static void one_tick(...)
1177          }
1178   }
1179  
1180 < #ifdef HAVE_PTHREADS
1180 > #ifdef USE_PTHREADS_SERVICES
1181   static void *tick_func(void *arg)
1182   {
1183 +        uint64 start = GetTicks_usec();
1184 +        int64 ticks = 0;
1185          uint64 next = GetTicks_usec();
1186          while (!tick_thread_cancel) {
1187                  one_tick();
# Line 749 | Line 1191 | static void *tick_func(void *arg)
1191                          Delay_usec(delay);
1192                  else if (delay < -16625)
1193                          next = GetTicks_usec();
1194 +                ticks++;
1195          }
1196 +        uint64 end = GetTicks_usec();
1197 +        D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1198          return NULL;
1199   }
1200   #endif
1201  
1202  
758 /*
759 *  Get current value of microsecond timer
760 */
761
762 uint64 GetTicks_usec(void)
763 {
764 #ifdef HAVE_CLOCK_GETTIME
765        struct timespec t;
766        clock_gettime(CLOCK_REALTIME, &t);
767        return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000;
768 #else
769        struct timeval t;
770        gettimeofday(&t, NULL);
771        return (uint64)t.tv_sec * 1000000 + t.tv_usec;
772 #endif
773 }
774
775
776 /*
777 *  Delay by specified number of microseconds (<1 second)
778 *  (adapted from SDL_Delay() source)
779 */
780
781 void Delay_usec(uint32 usec)
782 {
783        int was_error;
784 #ifndef __linux__       // Non-Linux implementations need to calculate time left
785        uint64 then, now, elapsed;
786 #endif
787        struct timeval tv;
788
789        // Set the timeout interval - Linux only needs to do this once
790 #ifdef __linux__
791        tv.tv_sec = 0;
792        tv.tv_usec = usec;
793 #else
794        then = GetTicks_usec();
795 #endif
796        do {
797                errno = 0;
798 #ifndef __linux__
799                /* Calculate the time interval left (in case of interrupt) */
800                now = GetTicks_usec();
801                elapsed = now - then;
802                then = now;
803                if (elapsed >= usec)
804                        break;
805                usec -= elapsed;
806                tv.tv_sec = 0;
807                tv.tv_usec = usec;
808 #endif
809                was_error = select(0, NULL, NULL, NULL, &tv);
810        } while (was_error && (errno == EINTR));
811 }
812
813
1203   #if !EMULATED_68K
1204   /*
1205   *  Virtual 68k interrupt handler
# Line 861 | Line 1250 | static void sigill_handler(int sig, int
1250  
1251   #define STORE_SR(v) \
1252          scp->sc_ps = (v) & 0xff; \
1253 <        EmulatedSR = (v) & 0x2700; \
1253 >        EmulatedSR = (v) & 0xe700; \
1254          if (((v) & 0x0700) == 0 && InterruptFlags) \
1255                  TriggerInterrupt();
1256  
# Line 924 | Line 1313 | static void sigill_handler(int sig, int
1313                  case 0x007c: {  // ori #xxxx,sr
1314                          uint16 sr = GET_SR | pc[1];
1315                          scp->sc_ps = sr & 0xff;         // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
1316 <                        EmulatedSR = sr & 0x2700;
1316 >                        EmulatedSR = sr & 0xe700;
1317                          INC_PC(4);
1318                          break;
1319                  }
# Line 1001 | Line 1390 | static void sigill_handler(int sig, int
1390                  }
1391  
1392                  case 0xf327:    // fsave -(sp)
1393 <                        goto ill;       //!!
1393 >                        regs->a[7] -= 4;
1394 >                        WriteMacInt32(regs->a[7], 0x41000000);  // Idle frame
1395 >                        scp->sc_sp = regs->a[7];
1396 >                        INC_PC(2);
1397 >                        break;
1398  
1399                  case 0xf35f:    // frestore (sp)+
1400 <                        goto ill;       //!!
1400 >                        regs->a[7] += 4;
1401 >                        scp->sc_sp = regs->a[7];
1402 >                        INC_PC(2);
1403 >                        break;
1404  
1405 <                case 0x4e73: {  // rte (only handles format 0)
1405 >                case 0x4e73: {  // rte
1406                          uint32 a7 = regs->a[7];
1407                          uint16 sr = ReadMacInt16(a7);
1408                          a7 += 2;
1409                          scp->sc_ps = sr & 0xff;
1410 <                        EmulatedSR = sr & 0x2700;
1410 >                        EmulatedSR = sr & 0xe700;
1411                          scp->sc_pc = ReadMacInt32(a7);
1412 <                        a7 += 6;
1413 <                        scp->sc_sp = regs->a[7] = a7;
1412 >                        a7 += 4;
1413 >                        uint16 format = ReadMacInt16(a7) >> 12;
1414 >                        a7 += 2;
1415 >                        static const int frame_adj[16] = {
1416 >                                0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0
1417 >                        };
1418 >                        scp->sc_sp = regs->a[7] = a7 + frame_adj[format];
1419                          break;
1420                  }
1421  
1422                  case 0x4e7a:    // movec cr,x
1423                          switch (pc[1]) {
1023                                case 0x8801:    // movec vbr,a0
1024                                        regs->a[0] = 0;
1025                                        break;
1026                                case 0x9801:    // movec vbr,a1
1027                                        regs->a[1] = 0;
1028                                        break;
1424                                  case 0x0002:    // movec cacr,d0
1425                                          regs->d[0] = 0x3111;
1426                                          break;
# Line 1033 | Line 1428 | static void sigill_handler(int sig, int
1428                                          regs->d[1] = 0x3111;
1429                                          break;
1430                                  case 0x0003:    // movec tc,d0
1431 +                                case 0x0004:    // movec itt0,d0
1432 +                                case 0x0005:    // movec itt1,d0
1433 +                                case 0x0006:    // movec dtt0,d0
1434 +                                case 0x0007:    // movec dtt1,d0
1435 +                                case 0x0806:    // movec urp,d0
1436 +                                case 0x0807:    // movec srp,d0
1437                                          regs->d[0] = 0;
1438                                          break;
1439 +                                case 0x1000:    // movec sfc,d1
1440 +                                case 0x1001:    // movec dfc,d1
1441                                  case 0x1003:    // movec tc,d1
1442 +                                case 0x1801:    // movec vbr,d1
1443                                          regs->d[1] = 0;
1444                                          break;
1445 +                                case 0x8801:    // movec vbr,a0
1446 +                                        regs->a[0] = 0;
1447 +                                        break;
1448 +                                case 0x9801:    // movec vbr,a1
1449 +                                        regs->a[1] = 0;
1450 +                                        break;
1451                                  default:
1452                                          goto ill;
1453                          }
# Line 1046 | Line 1456 | static void sigill_handler(int sig, int
1456  
1457                  case 0x4e7b:    // movec x,cr
1458                          switch (pc[1]) {
1459 +                                case 0x1000:    // movec d1,sfc
1460 +                                case 0x1001:    // movec d1,dfc
1461                                  case 0x0801:    // movec d0,vbr
1462 +                                case 0x1801:    // movec d1,vbr
1463                                          break;
1464                                  case 0x0002:    // movec d0,cacr
1465                                  case 0x1002:    // movec d1,cacr
# Line 1080 | Line 1493 | ill:           printf("SIGILL num %d, code %d\n",
1493                          for (int i=0; i<8; i++)
1494                                  printf("  a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
1495  
1496 +                        VideoQuitFullScreen();
1497   #ifdef ENABLE_MON
1498 <                        char *arg[2] = {"rmon", NULL};
1499 <                        mon(1, arg);
1498 >                        char *arg[4] = {"mon", "-m", "-r", NULL};
1499 >                        mon(3, arg);
1500   #endif
1501                          QuitEmulator();
1502                          break;
# Line 1140 | Line 1554 | void display_alert(int title_id, int pre
1554  
1555   void ErrorAlert(const char *text)
1556   {
1557 < #ifdef ENABLE_GTK
1557 >        if (gui_connection) {
1558 >                if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
1559 >                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
1560 >                        return;
1561 >        }
1562 > #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1563          if (PrefsFindBool("nogui") || x_display == NULL) {
1564                  printf(GetString(STR_SHELL_ERROR_PREFIX), text);
1565                  return;
# Line 1159 | Line 1578 | void ErrorAlert(const char *text)
1578  
1579   void WarningAlert(const char *text)
1580   {
1581 < #ifdef ENABLE_GTK
1581 >        if (gui_connection) {
1582 >                if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
1583 >                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
1584 >                        return;
1585 >        }
1586 > #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1587          if (PrefsFindBool("nogui") || x_display == NULL) {
1588                  printf(GetString(STR_SHELL_WARNING_PREFIX), text);
1589                  return;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines