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.68 by gbeauche, 2005-06-11T06:52:22Z

# 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) 1997-2005 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
# Line 57 | Line 68 | struct sigstate {
68   # include <X11/extensions/xf86dga.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 +
90 + #if USE_JIT
91 + extern void flush_icache_range(uint32 start, uint32 size); // from compemu_support.cpp
92 + #endif
93  
94   #ifdef ENABLE_MON
95   # include "mon.h"
# Line 81 | Line 101 | struct sigstate {
101  
102   // Constants
103   const char ROM_FILE_NAME[] = "ROM";
104 + #if !EMULATED_68K
105   const int SIG_STACK_SIZE = SIGSTKSZ;    // Size of signal stack
106 + #endif
107   const int SCRATCH_MEM_SIZE = 0x10000;   // Size of scratch memory area
108  
109  
# Line 101 | Line 123 | int CPUType;
123   bool CPUIs68060;
124   int FPUType;
125   bool TwentyFourBitAddressing;
126 + bool ThirtyThreeBitAddressing = false;
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  
155 #ifdef USE_MAPPED_MEMORY
156 extern char *address_space, *good_address_map;
157 #endif
158
195  
196   // Prototypes
197   static void *xpram_func(void *arg);
# Line 187 | Line 223 | char *strdup(const char *s)
223  
224  
225   /*
226 + *  Map memory that can be accessed from the Mac side
227 + */
228 +
229 + void *vm_acquire_mac(size_t size)
230 + {
231 +        void *m = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_33BIT);
232 +        if (m == NULL) {
233 +                ThirtyThreeBitAddressing = false;
234 +                m = vm_acquire(size);
235 +        }
236 +        return m;
237 + }
238 +
239 +
240 + /*
241 + *  SIGSEGV handler
242 + */
243 +
244 + static sigsegv_return_t sigsegv_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
245 + {
246 + #if ENABLE_VOSF
247 +        // Handle screen fault
248 +        extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t);
249 +        if (Screen_fault_handler(fault_address, fault_instruction))
250 +                return SIGSEGV_RETURN_SUCCESS;
251 + #endif
252 +
253 + #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
254 +        // Ignore writes to ROM
255 +        if (((uintptr)fault_address - (uintptr)ROMBaseHost) < ROMSize)
256 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
257 +
258 +        // Ignore all other faults, if requested
259 +        if (PrefsFindBool("ignoresegv"))
260 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
261 + #endif
262 +
263 +        return SIGSEGV_RETURN_FAILURE;
264 + }
265 +
266 + /*
267 + *  Dump state when everything went wrong after a SEGV
268 + */
269 +
270 + static void sigsegv_dump_state(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
271 + {
272 +        fprintf(stderr, "Caught SIGSEGV at address %p", fault_address);
273 +        if (fault_instruction != SIGSEGV_INVALID_PC)
274 +                fprintf(stderr, " [IP=%p]", fault_instruction);
275 +        fprintf(stderr, "\n");
276 + #if EMULATED_68K
277 +        uaecptr nextpc;
278 +        extern void m68k_dumpstate(uaecptr *nextpc);
279 +        m68k_dumpstate(&nextpc);
280 + #endif
281 + #if USE_JIT && JIT_DEBUG
282 +        extern void compiler_dumpstate(void);
283 +        compiler_dumpstate();
284 + #endif
285 +        VideoQuitFullScreen();
286 + #ifdef ENABLE_MON
287 +        char *arg[4] = {"mon", "-m", "-r", NULL};
288 +        mon(3, arg);
289 + #endif
290 +        QuitEmulator();
291 + }
292 +
293 +
294 + /*
295 + *  Update virtual clock and trigger interrupts if necessary
296 + */
297 +
298 + #ifdef USE_CPU_EMUL_SERVICES
299 + static uint64 n_check_ticks = 0;
300 + static uint64 emulated_ticks_start = 0;
301 + static uint64 emulated_ticks_count = 0;
302 + static int64 emulated_ticks_current = 0;
303 + static int32 emulated_ticks_quantum = 1000;
304 + int32 emulated_ticks = emulated_ticks_quantum;
305 +
306 + void cpu_do_check_ticks(void)
307 + {
308 + #if DEBUG
309 +        n_check_ticks++;
310 + #endif
311 +
312 +        uint64 now;
313 +        static uint64 next = 0;
314 +        if (next == 0)
315 +                next = emulated_ticks_start = GetTicks_usec();
316 +
317 +        // Update total instructions count
318 +        if (emulated_ticks <= 0) {
319 +                emulated_ticks_current += (emulated_ticks_quantum - emulated_ticks);
320 +                // XXX: can you really have a machine fast enough to overflow
321 +                // a 63-bit m68k instruction counter within 16 ms?
322 +                if (emulated_ticks_current < 0) {
323 +                        printf("WARNING: Overflowed 63-bit m68k instruction counter in less than 16 ms!\n");
324 +                        goto recalibrate_quantum;
325 +                }
326 +        }
327 +
328 +        // Check for interrupt opportunity
329 +        now = GetTicks_usec();
330 +        if (next < now) {
331 +                one_tick();
332 +                do {
333 +                        next += 16625;
334 +                } while (next < now);
335 +                emulated_ticks_count++;
336 +
337 +                // Recalibrate 1000 Hz quantum every 10 ticks
338 +                static uint64 last = 0;
339 +                if (last == 0)
340 +                        last = now;
341 +                else if (now - last > 166250) {
342 +                  recalibrate_quantum:
343 +                        emulated_ticks_quantum = ((uint64)emulated_ticks_current * 1000) / (now - last);
344 +                        emulated_ticks_current = 0;
345 +                        last = now;
346 +                }
347 +        }
348 +
349 +        // Update countdown
350 +        if (emulated_ticks <= 0)
351 +                emulated_ticks += emulated_ticks_quantum;
352 + }
353 + #endif
354 +
355 +
356 + /*
357   *  Main program
358   */
359  
360 + static void usage(const char *prg_name)
361 + {
362 +        printf(
363 +                "Usage: %s [OPTION...]\n"
364 +                "\nUnix options:\n"
365 +                "  --config FILE\n    read/write configuration from/to FILE\n"
366 +                "  --display STRING\n    X display to use\n"
367 +                "  --break ADDRESS\n    set ROM breakpoint\n"
368 +                "  --rominfo\n    dump ROM information\n", prg_name
369 +        );
370 +        LoadPrefs(); // read the prefs file so PrefsPrintUsage() will print the correct default values
371 +        PrefsPrintUsage();
372 +        exit(0);
373 + }
374 +
375   int main(int argc, char **argv)
376   {
377          char str[256];
# Line 204 | Line 386 | int main(int argc, char **argv)
386          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
387          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
388  
389 <        // Parse arguments
389 >        // Parse command line arguments
390          for (int i=1; i<argc; i++) {
391 <                if (strcmp(argv[i], "-display") == 0 && ++i < argc)
392 <                        x_display_name = argv[i];
393 <                else if (strcmp(argv[i], "-break") == 0 && ++i < argc)
394 <                        ROMBreakpoint = strtol(argv[i], NULL, 0);
395 <                else if (strcmp(argv[i], "-rominfo") == 0)
391 >                if (strcmp(argv[i], "--help") == 0) {
392 >                        usage(argv[0]);
393 > #ifndef USE_SDL_VIDEO
394 >                } else if (strcmp(argv[i], "--display") == 0) {
395 >                        i++; // don't remove the argument, gtk_init() needs it too
396 >                        if (i < argc)
397 >                                x_display_name = strdup(argv[i]);
398 > #endif
399 >                } else if (strcmp(argv[i], "--break") == 0) {
400 >                        argv[i++] = NULL;
401 >                        if (i < argc) {
402 >                                ROMBreakpoint = strtol(argv[i], NULL, 0);
403 >                                argv[i] = NULL;
404 >                        }
405 >                } else if (strcmp(argv[i], "--config") == 0) {
406 >                        argv[i++] = NULL;
407 >                        if (i < argc) {
408 >                                extern string UserPrefsPath; // from prefs_unix.cpp
409 >                                UserPrefsPath = argv[i];
410 >                                argv[i] = NULL;
411 >                        }
412 >                } else if (strcmp(argv[i], "--rominfo") == 0) {
413 >                        argv[i] = NULL;
414                          PrintROMInfo = true;
415 +                }
416 +        }
417 +
418 +        // Remove processed arguments
419 +        for (int i=1; i<argc; i++) {
420 +                int k;
421 +                for (k=i; k<argc; k++)
422 +                        if (argv[k] != NULL)
423 +                                break;
424 +                if (k > i) {
425 +                        k -= i;
426 +                        for (int j=i+k; j<argc; j++)
427 +                                argv[j-k] = argv[j];
428 +                        argc -= k;
429 +                }
430 +        }
431 +
432 + #ifdef ENABLE_GTK
433 + #ifdef HAVE_GNOMEUI
434 +        // Init GNOME/GTK
435 +        char version[16];
436 +        sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
437 +        gnome_init("Basilisk II", version, argc, argv);
438 + #else
439 +        // Init GTK
440 +        gtk_set_locale();
441 +        gtk_init(&argc, &argv);
442 + #endif
443 + #endif
444 +
445 +        // Read preferences
446 +        PrefsInit(argc, argv);
447 +
448 +        // Any command line arguments left?
449 +        for (int i=1; i<argc; i++) {
450 +                if (argv[i][0] == '-') {
451 +                        fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
452 +                        usage(argv[0]);
453 +                }
454          }
455  
456 + #ifndef USE_SDL_VIDEO
457          // Open display
458          x_display = XOpenDisplay(x_display_name);
459          if (x_display == NULL) {
# Line 227 | Line 467 | int main(int argc, char **argv)
467          // Fork out, so we can return from fullscreen mode when things get ugly
468          XF86DGAForkApp(DefaultScreen(x_display));
469   #endif
230
231 #ifdef ENABLE_GTK
232        // Init GTK
233        gtk_set_locale();
234        gtk_init(&argc, &argv);
470   #endif
471  
472 <        // Read preferences
473 <        PrefsInit();
472 > #ifdef USE_SDL
473 >        // Initialize SDL system
474 >        int sdl_flags = 0;
475 > #ifdef USE_SDL_VIDEO
476 >        sdl_flags |= SDL_INIT_VIDEO;
477 > #endif
478 > #ifdef USE_SDL_AUDIO
479 >        sdl_flags |= SDL_INIT_AUDIO;
480 > #endif
481 >        assert(sdl_flags != 0);
482 >        if (SDL_Init(sdl_flags) == -1) {
483 >                char str[256];
484 >                sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError());
485 >                ErrorAlert(str);
486 >                QuitEmulator();
487 >        }
488 >        atexit(SDL_Quit);
489 > #endif
490  
491          // Init system routines
492          SysInit();
# Line 245 | Line 496 | int main(int argc, char **argv)
496                  if (!PrefsEditor())
497                          QuitEmulator();
498  
499 <        // Open /dev/zero
500 <        zero_fd = open("/dev/zero", O_RDWR);
501 <        if (zero_fd < 0) {
251 <                sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
499 >        // Install the handler for SIGSEGV
500 >        if (!sigsegv_install_handler(sigsegv_handler)) {
501 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
502                  ErrorAlert(str);
503                  QuitEmulator();
504          }
505 +        
506 +        // Register dump state function when we got mad after a segfault
507 +        sigsegv_set_dump_state(sigsegv_dump_state);
508  
509          // Read RAM size
510          RAMSize = PrefsFindInt32("ramsize") & 0xfff00000;       // Round down to 1MB boundary
# Line 260 | Line 513 | int main(int argc, char **argv)
513                  RAMSize = 1024*1024;
514          }
515  
516 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
517 +        RAMSize = RAMSize & -getpagesize();                                     // Round down to page boundary
518 + #endif
519 +        
520 +        // Initialize VM system
521 +        vm_init();
522 +
523   #if REAL_ADDRESSING
524 <        // Create Low Memory area (0x0000..0x2000)
525 <        if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
524 >        // Flag: RAM and ROM are contigously allocated from address 0
525 >        bool memory_mapped_from_zero = false;
526 >        
527 >        // Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash
528 >        // when trying to map a too big chunk of memory starting at address 0
529 > #if defined(OS_solaris) || defined(OS_netbsd) || defined(PAGEZERO_HACK)
530 >        const bool can_map_all_memory = false;
531 > #else
532 >        const bool can_map_all_memory = true;
533 > #endif
534 >        
535 >        // Try to allocate all memory from 0x0000, if it is not known to crash
536 >        if (can_map_all_memory && (vm_acquire_fixed(0, RAMSize + 0x100000) == 0)) {
537 >                D(bug("Could allocate RAM and ROM from 0x0000\n"));
538 >                memory_mapped_from_zero = true;
539 >        }
540 >        
541 > #ifndef PAGEZERO_HACK
542 >        // Otherwise, just create the Low Memory area (0x0000..0x2000)
543 >        else if (vm_acquire_fixed(0, 0x2000) == 0) {
544 >                D(bug("Could allocate the Low Memory globals\n"));
545 >                lm_area_mapped = true;
546 >        }
547 >        
548 >        // Exit on failure
549 >        else {
550                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
551                  ErrorAlert(str);
552                  QuitEmulator();
553          }
270        lm_area_mapped = true;
554   #endif
555 + #endif /* REAL_ADDRESSING */
556  
557 < #if !EMULATED_68K
557 >        // Create areas for Mac RAM and ROM
558 > #if REAL_ADDRESSING
559 >        if (memory_mapped_from_zero) {
560 >                RAMBaseHost = (uint8 *)0;
561 >                ROMBaseHost = RAMBaseHost + RAMSize;
562 >        }
563 >        else
564 > #endif
565 >        {
566 > #ifdef USE_33BIT_ADDRESSING
567 >                // Speculatively enables 33-bit addressing
568 >                ThirtyThreeBitAddressing = true;
569 > #endif
570 >                RAMBaseHost = (uint8 *)vm_acquire_mac(RAMSize);
571 >                ROMBaseHost = (uint8 *)vm_acquire_mac(0x100000);
572 >                if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) {
573 >                        ErrorAlert(STR_NO_MEM_ERR);
574 >                        QuitEmulator();
575 >                }
576 >        }
577 >
578 > #if USE_SCRATCHMEM_SUBTERFUGE
579          // Allocate scratch memory
580 <        ScratchMem = (uint32)malloc(SCRATCH_MEM_SIZE);
581 <        if (ScratchMem == NULL) {
582 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
580 >        ScratchMem = (uint8 *)vm_acquire(SCRATCH_MEM_SIZE);
581 >        if (ScratchMem == VM_MAP_FAILED) {
582 >                ErrorAlert(STR_NO_MEM_ERR);
583                  QuitEmulator();
584          }
585          ScratchMem += SCRATCH_MEM_SIZE/2;       // ScratchMem points to middle of block
586   #endif
587  
588 <        // Create areas for Mac RAM and ROM
589 < #if defined(USE_MAPPED_MEMORY)
590 <    good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, zero_fd, 0);
591 <    address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
592 <    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];
588 > #if DIRECT_ADDRESSING
589 >        // RAMBaseMac shall always be zero
590 >        MEMBaseDiff = (uintptr)RAMBaseHost;
591 >        RAMBaseMac = 0;
592 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
593   #endif
594 < #if REAL_ADDRESSING && !EMULATED_68K
594 > #if REAL_ADDRESSING
595          RAMBaseMac = (uint32)RAMBaseHost;
596          ROMBaseMac = (uint32)ROMBaseHost;
597   #endif
598          D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
599          D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
600 <
600 >        
601          // Get rom file path from preferences
602          const char *rom_path = PrefsFindString("rom");
603  
604          // Load Mac ROM
605          int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
606          if (rom_fd < 0) {
607 <                ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
607 >                ErrorAlert(STR_NO_ROM_FILE_ERR);
608                  QuitEmulator();
609          }
610          printf(GetString(STR_READING_ROM_FILE));
611          ROMSize = lseek(rom_fd, 0, SEEK_END);
612          if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
613 <                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
613 >                ErrorAlert(STR_ROM_SIZE_ERR);
614                  close(rom_fd);
615                  QuitEmulator();
616          }
617          lseek(rom_fd, 0, SEEK_SET);
618          if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) {
619 <                ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
619 >                ErrorAlert(STR_ROM_FILE_READ_ERR);
620                  close(rom_fd);
621                  QuitEmulator();
622          }
# Line 359 | Line 646 | int main(int argc, char **argv)
646                  printf("WARNING: Cannot detect CPU type, assuming 68020\n");
647                  CPUType = 2;
648          }
649 <        FPUType = 0;    //!!
649 >        FPUType = 1;    // NetBSD has an FPU emulation, so the FPU ought to be available at all times
650          TwentyFourBitAddressing = false;
651   #endif
652  
# Line 368 | Line 655 | int main(int argc, char **argv)
655                  QuitEmulator();
656          D(bug("Initialization complete\n"));
657  
658 + #if !EMULATED_68K
659 +        // (Virtual) supervisor mode, disable interrupts
660 +        EmulatedSR = 0x2700;
661 +
662   #ifdef HAVE_PTHREADS
663          // Get handle of main thread
664          emul_thread = pthread_self();
665   #endif
666  
376 #if !EMULATED_68K
377        // (Virtual) supervisor mode, disable interrupts
378        EmulatedSR = 0x2700;
379
667          // Create and install stack for signal handlers
668          sig_stack = malloc(SIG_STACK_SIZE);
669          D(bug("Signal stack at %p\n", sig_stack));
670          if (sig_stack == NULL) {
671 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
671 >                ErrorAlert(STR_NOT_ENOUGH_MEMORY_ERR);
672                  QuitEmulator();
673          }
674          stack_t new_stack;
# Line 422 | Line 709 | int main(int argc, char **argv)
709   #ifdef ENABLE_MON
710          // Setup SIGINT handler to enter mon
711          sigemptyset(&sigint_sa.sa_mask);
712 <        sigint_sa.sa_handler = sigint_handler;
712 >        sigint_sa.sa_handler = (void (*)(int))sigint_handler;
713          sigint_sa.sa_flags = 0;
714          sigaction(SIGINT, &sigint_sa, NULL);
715   #endif
716  
717 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
717 > #ifndef USE_CPU_EMUL_SERVICES
718 > #if defined(HAVE_PTHREADS)
719 >
720 >        // POSIX threads available, start 60Hz thread
721 >        Set_pthread_attr(&tick_thread_attr, 0);
722 >        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
723 >        if (!tick_thread_active) {
724 >                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
725 >                ErrorAlert(str);
726 >                QuitEmulator();
727 >        }
728 >        D(bug("60Hz thread started\n"));
729 >
730 > #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
731  
732          // POSIX.4 timers and real-time signals available, start 60Hz timer
733          sigemptyset(&timer_sa.sa_mask);
734 <        timer_sa.sa_sigaction = one_tick;
734 >        timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick;
735          timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
736          if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
737                  sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
# Line 458 | Line 758 | int main(int argc, char **argv)
758          }
759          D(bug("60Hz timer started\n"));
760  
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
761   #else
762  
763          // Start 60Hz timer
764          sigemptyset(&timer_sa.sa_mask);         // Block virtual 68k interrupts during SIGARLM handling
765 + #if !EMULATED_68K
766          sigaddset(&timer_sa.sa_mask, SIG_IRQ);
767 + #endif
768          timer_sa.sa_handler = one_tick;
769          timer_sa.sa_flags = SA_ONSTACK | SA_RESTART;
770          if (sigaction(SIGALRM, &timer_sa, NULL) < 0) {
# Line 497 | Line 778 | int main(int argc, char **argv)
778          setitimer(ITIMER_REAL, &req, NULL);
779  
780   #endif
781 + #endif
782  
783 < #ifdef HAVE_PTHREADS
783 > #ifdef USE_PTHREADS_SERVICES
784          // Start XPRAM watchdog thread
785 <        memcpy(last_xpram, XPRAM, 256);
785 >        memcpy(last_xpram, XPRAM, XPRAM_SIZE);
786          xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
787          D(bug("XPRAM thread started\n"));
788   #endif
# Line 527 | Line 809 | void QuitEmulator(void)
809          Exit680x0();
810   #endif
811  
812 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
813 <        // Stop 60Hz timer
814 <        timer_delete(timer);
815 < #elif defined(HAVE_PTHREADS)
812 > #if defined(USE_CPU_EMUL_SERVICES)
813 >        // Show statistics
814 >        uint64 emulated_ticks_end = GetTicks_usec();
815 >        D(bug("%ld ticks in %ld usec = %f ticks/sec [%ld tick checks]\n",
816 >                  (long)emulated_ticks_count, (long)(emulated_ticks_end - emulated_ticks_start),
817 >                  emulated_ticks_count * 1000000.0 / (emulated_ticks_end - emulated_ticks_start), (long)n_check_ticks));
818 > #elif defined(USE_PTHREADS_SERVICES)
819          // Stop 60Hz thread
820          if (tick_thread_active) {
821                  tick_thread_cancel = true;
# Line 539 | Line 824 | void QuitEmulator(void)
824   #endif
825                  pthread_join(tick_thread, NULL);
826          }
827 + #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
828 +        // Stop 60Hz timer
829 +        timer_delete(timer);
830   #else
831          struct itimerval req;
832          req.it_interval.tv_sec = req.it_value.tv_sec = 0;
# Line 546 | Line 834 | void QuitEmulator(void)
834          setitimer(ITIMER_REAL, &req, NULL);
835   #endif
836  
837 < #ifdef HAVE_PTHREADS
837 > #ifdef USE_PTHREADS_SERVICES
838          // Stop XPRAM watchdog thread
839          if (xpram_thread_active) {
840                  xpram_thread_cancel = true;
# Line 560 | Line 848 | void QuitEmulator(void)
848          // Deinitialize everything
849          ExitAll();
850  
851 <        // Delete ROM area
852 <        delete[] ROMBaseHost;
853 <
854 <        // Delete RAM area
855 <        delete[] RAMBaseHost;
851 >        // Free ROM/RAM areas
852 >        if (RAMBaseHost != VM_MAP_FAILED) {
853 >                vm_release(RAMBaseHost, RAMSize);
854 >                RAMBaseHost = NULL;
855 >        }
856 >        if (ROMBaseHost != VM_MAP_FAILED) {
857 >                vm_release(ROMBaseHost, 0x100000);
858 >                ROMBaseHost = NULL;
859 >        }
860  
861 < #if !EMULATED_68K
861 > #if USE_SCRATCHMEM_SUBTERFUGE
862          // Delete scratch memory area
863 <        if (ScratchMem)
864 <                free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
863 >        if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
864 >                vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
865 >                ScratchMem = NULL;
866 >        }
867   #endif
868  
869   #if REAL_ADDRESSING
870          // Delete Low Memory area
871          if (lm_area_mapped)
872 <                munmap((char *)0x0000, 0x2000);
872 >                vm_release(0, 0x2000);
873   #endif
874 <
875 <        // Close /dev/zero
876 <        if (zero_fd > 0)
583 <                close(zero_fd);
874 >        
875 >        // Exit VM wrappers
876 >        vm_exit();
877  
878          // Exit system routines
879          SysExit();
# Line 589 | Line 882 | void QuitEmulator(void)
882          PrefsExit();
883  
884          // Close X11 server connection
885 + #ifndef USE_SDL_VIDEO
886          if (x_display)
887                  XCloseDisplay(x_display);
888 + #endif
889  
890          exit(0);
891   }
# Line 603 | Line 898 | void QuitEmulator(void)
898  
899   void FlushCodeCache(void *start, uint32 size)
900   {
901 + #if USE_JIT
902 +    if (UseJIT)
903 +                flush_icache_range((uintptr)start, size);
904 + #endif
905   #if !EMULATED_68K && defined(__NetBSD__)
906          m68k_sync_icache(start, size);
907   #endif
# Line 620 | Line 919 | static void sigint_handler(...)
919          uaecptr nextpc;
920          extern void m68k_dumpstate(uaecptr *nextpc);
921          m68k_dumpstate(&nextpc);
922 < #else
923 <        char *arg[2] = {"rmon", NULL};
924 <        mon(1, arg);
922 > #endif
923 >        VideoQuitFullScreen();
924 >        char *arg[4] = {"mon", "-m", "-r", NULL};
925 >        mon(3, arg);
926          QuitEmulator();
927 + }
928 + #endif
929 +
930 +
931 + #ifdef HAVE_PTHREADS
932 + /*
933 + *  Pthread configuration
934 + */
935 +
936 + void Set_pthread_attr(pthread_attr_t *attr, int priority)
937 + {
938 +        pthread_attr_init(attr);
939 + #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
940 +        // Some of these only work for superuser
941 +        if (geteuid() == 0) {
942 +                pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
943 +                pthread_attr_setschedpolicy(attr, SCHED_FIFO);
944 +                struct sched_param fifo_param;
945 +                fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
946 +                                              sched_get_priority_max(SCHED_FIFO)) / 2 +
947 +                                             priority);
948 +                pthread_attr_setschedparam(attr, &fifo_param);
949 +        }
950 +        if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
951 + #ifdef PTHREAD_SCOPE_BOUND_NP
952 +            // If system scope is not available (eg. we're not running
953 +            // with CAP_SCHED_MGT capability on an SGI box), try bound
954 +            // scope.  It exposes pthread scheduling to the kernel,
955 +            // without setting realtime priority.
956 +            pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
957 + #endif
958 +        }
959   #endif
960   }
961 + #endif // HAVE_PTHREADS
962 +
963 +
964 + /*
965 + *  Mutexes
966 + */
967 +
968 + #ifdef HAVE_PTHREADS
969 +
970 + struct B2_mutex {
971 +        B2_mutex() {
972 +            pthread_mutexattr_t attr;
973 +            pthread_mutexattr_init(&attr);
974 +            // Initialize the mutex for priority inheritance --
975 +            // required for accurate timing.
976 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__)
977 +            pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
978 + #endif
979 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
980 +            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
981 + #endif
982 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
983 +            pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
984 + #endif
985 +            pthread_mutex_init(&m, &attr);
986 +            pthread_mutexattr_destroy(&attr);
987 +        }
988 +        ~B2_mutex() {
989 +            pthread_mutex_trylock(&m); // Make sure it's locked before
990 +            pthread_mutex_unlock(&m);  // unlocking it.
991 +            pthread_mutex_destroy(&m);
992 +        }
993 +        pthread_mutex_t m;
994 + };
995 +
996 + B2_mutex *B2_create_mutex(void)
997 + {
998 +        return new B2_mutex;
999 + }
1000 +
1001 + void B2_lock_mutex(B2_mutex *mutex)
1002 + {
1003 +        pthread_mutex_lock(&mutex->m);
1004 + }
1005 +
1006 + void B2_unlock_mutex(B2_mutex *mutex)
1007 + {
1008 +        pthread_mutex_unlock(&mutex->m);
1009 + }
1010 +
1011 + void B2_delete_mutex(B2_mutex *mutex)
1012 + {
1013 +        delete mutex;
1014 + }
1015 +
1016 + #else
1017 +
1018 + struct B2_mutex {
1019 +        int dummy;
1020 + };
1021 +
1022 + B2_mutex *B2_create_mutex(void)
1023 + {
1024 +        return new B2_mutex;
1025 + }
1026 +
1027 + void B2_lock_mutex(B2_mutex *mutex)
1028 + {
1029 + }
1030 +
1031 + void B2_unlock_mutex(B2_mutex *mutex)
1032 + {
1033 + }
1034 +
1035 + void B2_delete_mutex(B2_mutex *mutex)
1036 + {
1037 +        delete mutex;
1038 + }
1039 +
1040   #endif
1041  
1042  
# Line 638 | Line 1049 | uint32 InterruptFlags = 0;
1049   #if EMULATED_68K
1050   void SetInterruptFlag(uint32 flag)
1051   {
1052 < #ifdef HAVE_PTHREADS
642 <        pthread_mutex_lock(&intflag_lock);
1052 >        LOCK_INTFLAGS;
1053          InterruptFlags |= flag;
1054 <        pthread_mutex_unlock(&intflag_lock);
645 < #else
646 <        InterruptFlags |= flag;         // Pray that this is an atomic operation...
647 < #endif
1054 >        UNLOCK_INTFLAGS;
1055   }
1056  
1057   void ClearInterruptFlag(uint32 flag)
1058   {
1059 < #ifdef HAVE_PTHREADS
653 <        pthread_mutex_lock(&intflag_lock);
1059 >        LOCK_INTFLAGS;
1060          InterruptFlags &= ~flag;
1061 <        pthread_mutex_unlock(&intflag_lock);
656 < #else
657 <        InterruptFlags &= ~flag;
658 < #endif
1061 >        UNLOCK_INTFLAGS;
1062   }
1063   #endif
1064  
# Line 668 | Line 1071 | void TriggerInterrupt(void)
1071          raise(SIG_IRQ);
1072   #endif
1073   }
1074 +
1075 + void TriggerNMI(void)
1076 + {
1077 +        // not yet supported
1078 + }
1079   #endif
1080  
1081  
# Line 677 | Line 1085 | void TriggerInterrupt(void)
1085  
1086   static void xpram_watchdog(void)
1087   {
1088 <        if (memcmp(last_xpram, XPRAM, 256)) {
1089 <                memcpy(last_xpram, XPRAM, 256);
1088 >        if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
1089 >                memcpy(last_xpram, XPRAM, XPRAM_SIZE);
1090                  SaveXPRAM();
1091          }
1092   }
1093  
1094 < #ifdef HAVE_PTHREADS
1094 > #ifdef USE_PTHREADS_SERVICES
1095   static void *xpram_func(void *arg)
1096   {
1097          while (!xpram_thread_cancel) {
1098                  for (int i=0; i<60 && !xpram_thread_cancel; i++)
1099 <                        Delay_usec(1000000);
1099 >                        Delay_usec(999999);             // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true
1100                  xpram_watchdog();
1101          }
1102          return NULL;
# Line 705 | Line 1113 | static void one_second(void)
1113          // Pseudo Mac 1Hz interrupt, update local time
1114          WriteMacInt32(0x20c, TimerDateTime());
1115  
1116 <        SetInterruptFlag(INTFLAG_60HZ);
1116 >        SetInterruptFlag(INTFLAG_1HZ);
1117          TriggerInterrupt();
1118  
1119 < #ifndef HAVE_PTHREADS
1119 > #ifndef USE_PTHREADS_SERVICES
1120          static int second_counter = 0;
1121          if (++second_counter > 60) {
1122                  second_counter = 0;
# Line 725 | Line 1133 | static void one_tick(...)
1133                  one_second();
1134          }
1135  
1136 < #ifndef HAVE_PTHREADS
1137 <        // No threads available, perform video refresh from here
1136 > #if !defined(USE_PTHREADS_SERVICES) && !defined(USE_SDL_VIDEO)
1137 >        // No threads available, perform video refresh and networking from here
1138          VideoRefresh();
1139 +        SetInterruptFlag(INTFLAG_ETHER);
1140   #endif
1141  
1142          // Trigger 60Hz interrupt
# Line 737 | Line 1146 | static void one_tick(...)
1146          }
1147   }
1148  
1149 < #ifdef HAVE_PTHREADS
1149 > #ifdef USE_PTHREADS_SERVICES
1150   static void *tick_func(void *arg)
1151   {
1152 +        uint64 start = GetTicks_usec();
1153 +        int64 ticks = 0;
1154          uint64 next = GetTicks_usec();
1155          while (!tick_thread_cancel) {
1156                  one_tick();
# Line 749 | Line 1160 | static void *tick_func(void *arg)
1160                          Delay_usec(delay);
1161                  else if (delay < -16625)
1162                          next = GetTicks_usec();
1163 +                ticks++;
1164          }
1165 +        uint64 end = GetTicks_usec();
1166 +        D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1167          return NULL;
1168   }
1169   #endif
1170  
1171  
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
1172   #if !EMULATED_68K
1173   /*
1174   *  Virtual 68k interrupt handler
# Line 861 | Line 1219 | static void sigill_handler(int sig, int
1219  
1220   #define STORE_SR(v) \
1221          scp->sc_ps = (v) & 0xff; \
1222 <        EmulatedSR = (v) & 0x2700; \
1222 >        EmulatedSR = (v) & 0xe700; \
1223          if (((v) & 0x0700) == 0 && InterruptFlags) \
1224                  TriggerInterrupt();
1225  
# Line 924 | Line 1282 | static void sigill_handler(int sig, int
1282                  case 0x007c: {  // ori #xxxx,sr
1283                          uint16 sr = GET_SR | pc[1];
1284                          scp->sc_ps = sr & 0xff;         // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
1285 <                        EmulatedSR = sr & 0x2700;
1285 >                        EmulatedSR = sr & 0xe700;
1286                          INC_PC(4);
1287                          break;
1288                  }
# Line 1001 | Line 1359 | static void sigill_handler(int sig, int
1359                  }
1360  
1361                  case 0xf327:    // fsave -(sp)
1362 <                        goto ill;       //!!
1362 >                        regs->a[7] -= 4;
1363 >                        WriteMacInt32(regs->a[7], 0x41000000);  // Idle frame
1364 >                        scp->sc_sp = regs->a[7];
1365 >                        INC_PC(2);
1366 >                        break;
1367  
1368                  case 0xf35f:    // frestore (sp)+
1369 <                        goto ill;       //!!
1369 >                        regs->a[7] += 4;
1370 >                        scp->sc_sp = regs->a[7];
1371 >                        INC_PC(2);
1372 >                        break;
1373  
1374 <                case 0x4e73: {  // rte (only handles format 0)
1374 >                case 0x4e73: {  // rte
1375                          uint32 a7 = regs->a[7];
1376                          uint16 sr = ReadMacInt16(a7);
1377                          a7 += 2;
1378                          scp->sc_ps = sr & 0xff;
1379 <                        EmulatedSR = sr & 0x2700;
1379 >                        EmulatedSR = sr & 0xe700;
1380                          scp->sc_pc = ReadMacInt32(a7);
1381 <                        a7 += 6;
1382 <                        scp->sc_sp = regs->a[7] = a7;
1381 >                        a7 += 4;
1382 >                        uint16 format = ReadMacInt16(a7) >> 12;
1383 >                        a7 += 2;
1384 >                        static const int frame_adj[16] = {
1385 >                                0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0
1386 >                        };
1387 >                        scp->sc_sp = regs->a[7] = a7 + frame_adj[format];
1388                          break;
1389                  }
1390  
1391                  case 0x4e7a:    // movec cr,x
1392                          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;
1393                                  case 0x0002:    // movec cacr,d0
1394                                          regs->d[0] = 0x3111;
1395                                          break;
# Line 1033 | Line 1397 | static void sigill_handler(int sig, int
1397                                          regs->d[1] = 0x3111;
1398                                          break;
1399                                  case 0x0003:    // movec tc,d0
1400 +                                case 0x0004:    // movec itt0,d0
1401 +                                case 0x0005:    // movec itt1,d0
1402 +                                case 0x0006:    // movec dtt0,d0
1403 +                                case 0x0007:    // movec dtt1,d0
1404 +                                case 0x0806:    // movec urp,d0
1405 +                                case 0x0807:    // movec srp,d0
1406                                          regs->d[0] = 0;
1407                                          break;
1408 +                                case 0x1000:    // movec sfc,d1
1409 +                                case 0x1001:    // movec dfc,d1
1410                                  case 0x1003:    // movec tc,d1
1411 +                                case 0x1801:    // movec vbr,d1
1412                                          regs->d[1] = 0;
1413                                          break;
1414 +                                case 0x8801:    // movec vbr,a0
1415 +                                        regs->a[0] = 0;
1416 +                                        break;
1417 +                                case 0x9801:    // movec vbr,a1
1418 +                                        regs->a[1] = 0;
1419 +                                        break;
1420                                  default:
1421                                          goto ill;
1422                          }
# Line 1046 | Line 1425 | static void sigill_handler(int sig, int
1425  
1426                  case 0x4e7b:    // movec x,cr
1427                          switch (pc[1]) {
1428 +                                case 0x1000:    // movec d1,sfc
1429 +                                case 0x1001:    // movec d1,dfc
1430                                  case 0x0801:    // movec d0,vbr
1431 +                                case 0x1801:    // movec d1,vbr
1432                                          break;
1433                                  case 0x0002:    // movec d0,cacr
1434                                  case 0x1002:    // movec d1,cacr
# Line 1080 | Line 1462 | ill:           printf("SIGILL num %d, code %d\n",
1462                          for (int i=0; i<8; i++)
1463                                  printf("  a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
1464  
1465 +                        VideoQuitFullScreen();
1466   #ifdef ENABLE_MON
1467 <                        char *arg[2] = {"rmon", NULL};
1468 <                        mon(1, arg);
1467 >                        char *arg[4] = {"mon", "-m", "-r", NULL};
1468 >                        mon(3, arg);
1469   #endif
1470                          QuitEmulator();
1471                          break;
# Line 1140 | Line 1523 | void display_alert(int title_id, int pre
1523  
1524   void ErrorAlert(const char *text)
1525   {
1526 < #ifdef ENABLE_GTK
1526 > #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1527          if (PrefsFindBool("nogui") || x_display == NULL) {
1528                  printf(GetString(STR_SHELL_ERROR_PREFIX), text);
1529                  return;
# Line 1159 | Line 1542 | void ErrorAlert(const char *text)
1542  
1543   void WarningAlert(const char *text)
1544   {
1545 < #ifdef ENABLE_GTK
1545 > #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1546          if (PrefsFindBool("nogui") || x_display == NULL) {
1547                  printf(GetString(STR_SHELL_WARNING_PREFIX), text);
1548                  return;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines