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.13 by cebix, 2000-07-13T16:12:32Z vs.
Revision 1.77 by gbeauche, 2007-01-13T18:21:30Z

# 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 + #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 bool lm_area_mapped = false;                                     // Flag: Low Memory area mmap()ped
112 < 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 123 | 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  
126 #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 134 | 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)
137 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
188   static void sigint_handler(...);
189   #endif
190  
191 < #ifdef USE_MAPPED_MEMORY
192 < extern char *address_space, *good_address_map;
191 > #if REAL_ADDRESSING
192 > static bool lm_area_mapped = false;     // Flag: Low Memory area mmap()ped
193   #endif
194  
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
200   static void *xpram_func(void *arg);
# Line 184 | 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_address_t fault_address, sigsegv_address_t fault_instruction)
249 + {
250 + #if ENABLE_VOSF
251 +        // Handle screen fault
252 +        extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t);
253 +        if (Screen_fault_handler(fault_address, fault_instruction))
254 +                return SIGSEGV_RETURN_SUCCESS;
255 + #endif
256 +
257 + #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
258 +        // Ignore writes to ROM
259 +        if (((uintptr)fault_address - (uintptr)ROMBaseHost) < ROMSize)
260 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
261 +
262 +        // Ignore all other faults, if requested
263 +        if (PrefsFindBool("ignoresegv"))
264 +                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
265 + #endif
266 +
267 +        return SIGSEGV_RETURN_FAILURE;
268 + }
269 +
270 + /*
271 + *  Dump state when everything went wrong after a SEGV
272 + */
273 +
274 + static void sigsegv_dump_state(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
275 + {
276 +        fprintf(stderr, "Caught SIGSEGV at address %p", fault_address);
277 +        if (fault_instruction != SIGSEGV_INVALID_PC)
278 +                fprintf(stderr, " [IP=%p]", fault_instruction);
279 +        fprintf(stderr, "\n");
280 + #if EMULATED_68K
281 +        uaecptr nextpc;
282 +        extern void m68k_dumpstate(uaecptr *nextpc);
283 +        m68k_dumpstate(&nextpc);
284 + #endif
285 + #if USE_JIT && JIT_DEBUG
286 +        extern void compiler_dumpstate(void);
287 +        compiler_dumpstate();
288 + #endif
289 +        VideoQuitFullScreen();
290 + #ifdef ENABLE_MON
291 +        char *arg[4] = {"mon", "-m", "-r", NULL};
292 +        mon(3, arg);
293 + #endif
294 +        QuitEmulator();
295 + }
296 +
297 +
298 + /*
299 + *  Update virtual clock and trigger interrupts if necessary
300 + */
301 +
302 + #ifdef USE_CPU_EMUL_SERVICES
303 + static uint64 n_check_ticks = 0;
304 + static uint64 emulated_ticks_start = 0;
305 + static uint64 emulated_ticks_count = 0;
306 + static int64 emulated_ticks_current = 0;
307 + static int32 emulated_ticks_quantum = 1000;
308 + int32 emulated_ticks = emulated_ticks_quantum;
309 +
310 + void cpu_do_check_ticks(void)
311 + {
312 + #if DEBUG
313 +        n_check_ticks++;
314 + #endif
315 +
316 +        uint64 now;
317 +        static uint64 next = 0;
318 +        if (next == 0)
319 +                next = emulated_ticks_start = GetTicks_usec();
320 +
321 +        // Update total instructions count
322 +        if (emulated_ticks <= 0) {
323 +                emulated_ticks_current += (emulated_ticks_quantum - emulated_ticks);
324 +                // XXX: can you really have a machine fast enough to overflow
325 +                // a 63-bit m68k instruction counter within 16 ms?
326 +                if (emulated_ticks_current < 0) {
327 +                        printf("WARNING: Overflowed 63-bit m68k instruction counter in less than 16 ms!\n");
328 +                        goto recalibrate_quantum;
329 +                }
330 +        }
331 +
332 +        // Check for interrupt opportunity
333 +        now = GetTicks_usec();
334 +        if (next < now) {
335 +                one_tick();
336 +                do {
337 +                        next += 16625;
338 +                } while (next < now);
339 +                emulated_ticks_count++;
340 +
341 +                // Recalibrate 1000 Hz quantum every 10 ticks
342 +                static uint64 last = 0;
343 +                if (last == 0)
344 +                        last = now;
345 +                else if (now - last > 166250) {
346 +                  recalibrate_quantum:
347 +                        emulated_ticks_quantum = ((uint64)emulated_ticks_current * 1000) / (now - last);
348 +                        emulated_ticks_current = 0;
349 +                        last = now;
350 +                }
351 +        }
352 +
353 +        // Update countdown
354 +        if (emulated_ticks <= 0)
355 +                emulated_ticks += emulated_ticks_quantum;
356 + }
357 + #endif
358 +
359 +
360 + /*
361   *  Main program
362   */
363  
364 + static void usage(const char *prg_name)
365 + {
366 +        printf(
367 +                "Usage: %s [OPTION...]\n"
368 +                "\nUnix options:\n"
369 +                "  --config FILE\n    read/write configuration from/to FILE\n"
370 +                "  --display STRING\n    X display to use\n"
371 +                "  --break ADDRESS\n    set ROM breakpoint\n"
372 +                "  --rominfo\n    dump ROM information\n", prg_name
373 +        );
374 +        LoadPrefs(); // read the prefs file so PrefsPrintUsage() will print the correct default values
375 +        PrefsPrintUsage();
376 +        exit(0);
377 + }
378 +
379   int main(int argc, char **argv)
380   {
381          char str[256];
# Line 201 | Line 390 | int main(int argc, char **argv)
390          printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
391          printf(" %s\n", GetString(STR_ABOUT_TEXT2));
392  
393 <        // Parse arguments
393 >        // Parse command line arguments
394          for (int i=1; i<argc; i++) {
395 <                if (strcmp(argv[i], "-display") == 0 && ++i < argc)
396 <                        x_display_name = argv[i];
397 <                else if (strcmp(argv[i], "-break") == 0 && ++i < argc)
398 <                        ROMBreakpoint = strtol(argv[i], NULL, 0);
399 <                else if (strcmp(argv[i], "-rominfo") == 0)
395 >                if (strcmp(argv[i], "--help") == 0) {
396 >                        usage(argv[0]);
397 > #ifndef USE_SDL_VIDEO
398 >                } else if (strcmp(argv[i], "--display") == 0) {
399 >                        i++; // don't remove the argument, gtk_init() needs it too
400 >                        if (i < argc)
401 >                                x_display_name = strdup(argv[i]);
402 > #endif
403 >                } else if (strcmp(argv[i], "--gui-connection") == 0) {
404 >                        argv[i++] = NULL;
405 >                        if (i < argc) {
406 >                                gui_connection_path = argv[i];
407 >                                argv[i] = NULL;
408 >                        }
409 >                } else if (strcmp(argv[i], "--break") == 0) {
410 >                        argv[i++] = NULL;
411 >                        if (i < argc) {
412 >                                ROMBreakpoint = strtol(argv[i], NULL, 0);
413 >                                argv[i] = NULL;
414 >                        }
415 >                } else if (strcmp(argv[i], "--config") == 0) {
416 >                        argv[i++] = NULL;
417 >                        if (i < argc) {
418 >                                extern string UserPrefsPath; // from prefs_unix.cpp
419 >                                UserPrefsPath = argv[i];
420 >                                argv[i] = NULL;
421 >                        }
422 >                } else if (strcmp(argv[i], "--rominfo") == 0) {
423 >                        argv[i] = NULL;
424                          PrintROMInfo = true;
425 +                }
426 +        }
427 +
428 +        // Remove processed arguments
429 +        for (int i=1; i<argc; i++) {
430 +                int k;
431 +                for (k=i; k<argc; k++)
432 +                        if (argv[k] != NULL)
433 +                                break;
434 +                if (k > i) {
435 +                        k -= i;
436 +                        for (int j=i+k; j<argc; j++)
437 +                                argv[j-k] = argv[j];
438 +                        argc -= k;
439 +                }
440          }
441  
442 +        // Connect to the external GUI
443 +        if (gui_connection_path) {
444 +                if ((gui_connection = rpc_init_client(gui_connection_path)) == NULL) {
445 +                        fprintf(stderr, "Failed to initialize RPC client connection to the GUI\n");
446 +                        return 1;
447 +                }
448 +        }
449 +
450 + #ifdef ENABLE_GTK
451 +        if (!gui_connection) {
452 + #ifdef HAVE_GNOMEUI
453 +                // Init GNOME/GTK
454 +                char version[16];
455 +                sprintf(version, "%d.%d", VERSION_MAJOR, VERSION_MINOR);
456 +                gnome_init("Basilisk II", version, argc, argv);
457 + #else
458 +                // Init GTK
459 +                gtk_set_locale();
460 +                gtk_init(&argc, &argv);
461 + #endif
462 +        }
463 + #endif
464 +
465 +        // Read preferences
466 +        PrefsInit(argc, argv);
467 +
468 +        // Any command line arguments left?
469 +        for (int i=1; i<argc; i++) {
470 +                if (argv[i][0] == '-') {
471 +                        fprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
472 +                        usage(argv[0]);
473 +                }
474 +        }
475 +
476 + #ifndef USE_SDL_VIDEO
477          // Open display
478          x_display = XOpenDisplay(x_display_name);
479          if (x_display == NULL) {
# Line 224 | Line 487 | int main(int argc, char **argv)
487          // Fork out, so we can return from fullscreen mode when things get ugly
488          XF86DGAForkApp(DefaultScreen(x_display));
489   #endif
227
228 #ifdef ENABLE_GTK
229        // Init GTK
230        gtk_set_locale();
231        gtk_init(&argc, &argv);
490   #endif
491  
492 <        // Read preferences
493 <        PrefsInit();
492 > #ifdef USE_SDL
493 >        // Initialize SDL system
494 >        int sdl_flags = 0;
495 > #ifdef USE_SDL_VIDEO
496 >        sdl_flags |= SDL_INIT_VIDEO;
497 > #endif
498 > #ifdef USE_SDL_AUDIO
499 >        sdl_flags |= SDL_INIT_AUDIO;
500 > #endif
501 >        assert(sdl_flags != 0);
502 >        if (SDL_Init(sdl_flags) == -1) {
503 >                char str[256];
504 >                sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError());
505 >                ErrorAlert(str);
506 >                QuitEmulator();
507 >        }
508 >        atexit(SDL_Quit);
509 > #endif
510  
511          // Init system routines
512          SysInit();
513  
514          // Show preferences editor
515 <        if (!PrefsFindBool("nogui"))
515 >        if (!gui_connection && !PrefsFindBool("nogui"))
516                  if (!PrefsEditor())
517                          QuitEmulator();
518  
519 <        // Open /dev/zero
520 <        zero_fd = open("/dev/zero", O_RDWR);
521 <        if (zero_fd < 0) {
248 <                sprintf(str, GetString(STR_NO_DEV_ZERO_ERR), strerror(errno));
519 >        // Install the handler for SIGSEGV
520 >        if (!sigsegv_install_handler(sigsegv_handler)) {
521 >                sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno));
522                  ErrorAlert(str);
523                  QuitEmulator();
524          }
525 +        
526 +        // Register dump state function when we got mad after a segfault
527 +        sigsegv_set_dump_state(sigsegv_dump_state);
528  
529          // Read RAM size
530          RAMSize = PrefsFindInt32("ramsize") & 0xfff00000;       // Round down to 1MB boundary
# Line 256 | Line 532 | int main(int argc, char **argv)
532                  WarningAlert(GetString(STR_SMALL_RAM_WARN));
533                  RAMSize = 1024*1024;
534          }
535 +        if (RAMSize > 1023*1024*1024)                                           // Cap to 1023MB (APD crashes at 1GB)
536 +                RAMSize = 1023*1024*1024;
537 +
538 + #if REAL_ADDRESSING || DIRECT_ADDRESSING
539 +        RAMSize = RAMSize & -getpagesize();                                     // Round down to page boundary
540 + #endif
541 +        
542 +        // Initialize VM system
543 +        vm_init();
544  
545   #if REAL_ADDRESSING
546 <        // Create Low Memory area (0x0000..0x2000)
547 <        if (mmap((char *)0x0000, 0x2000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
546 >        // Flag: RAM and ROM are contigously allocated from address 0
547 >        bool memory_mapped_from_zero = false;
548 >
549 >        // Make sure to map RAM & ROM at address 0 only on platforms that
550 >        // supports linker scripts to relocate the Basilisk II executable
551 >        // above 0x70000000
552 > #if HAVE_LINKER_SCRIPT
553 >        const bool can_map_all_memory = true;
554 > #else
555 >        const bool can_map_all_memory = false;
556 > #endif
557 >        
558 >        // Try to allocate all memory from 0x0000, if it is not known to crash
559 >        if (can_map_all_memory && (vm_acquire_mac_fixed(0, RAMSize + 0x100000) == 0)) {
560 >                D(bug("Could allocate RAM and ROM from 0x0000\n"));
561 >                memory_mapped_from_zero = true;
562 >        }
563 >        
564 > #ifndef PAGEZERO_HACK
565 >        // Otherwise, just create the Low Memory area (0x0000..0x2000)
566 >        else if (vm_acquire_mac_fixed(0, 0x2000) == 0) {
567 >                D(bug("Could allocate the Low Memory globals\n"));
568 >                lm_area_mapped = true;
569 >        }
570 >        
571 >        // Exit on failure
572 >        else {
573                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
574                  ErrorAlert(str);
575                  QuitEmulator();
576          }
267        lm_area_mapped = true;
577   #endif
578 + #endif /* REAL_ADDRESSING */
579  
580 < #if !EMULATED_68K
580 >        // Create areas for Mac RAM and ROM
581 > #if REAL_ADDRESSING
582 >        if (memory_mapped_from_zero) {
583 >                RAMBaseHost = (uint8 *)0;
584 >                ROMBaseHost = RAMBaseHost + RAMSize;
585 >        }
586 >        else
587 > #endif
588 >        {
589 >                uint8 *ram_rom_area = (uint8 *)vm_acquire_mac(RAMSize + 0x100000);
590 >                if (ram_rom_area == VM_MAP_FAILED) {    
591 >                        ErrorAlert(STR_NO_MEM_ERR);
592 >                        QuitEmulator();
593 >                }
594 >                RAMBaseHost = ram_rom_area;
595 >                ROMBaseHost = RAMBaseHost + RAMSize;
596 >        }
597 >
598 > #if USE_SCRATCHMEM_SUBTERFUGE
599          // Allocate scratch memory
600 <        ScratchMem = (uint32)malloc(SCRATCH_MEM_SIZE);
601 <        if (ScratchMem == NULL) {
602 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
600 >        ScratchMem = (uint8 *)vm_acquire_mac(SCRATCH_MEM_SIZE);
601 >        if (ScratchMem == VM_MAP_FAILED) {
602 >                ErrorAlert(STR_NO_MEM_ERR);
603                  QuitEmulator();
604          }
605          ScratchMem += SCRATCH_MEM_SIZE/2;       // ScratchMem points to middle of block
606   #endif
607  
608 <        // Create areas for Mac RAM and ROM
609 < #if defined(USE_MAPPED_MEMORY)
610 <    good_address_map = (char *)mmap(NULL, 1<<24, PROT_READ, MAP_PRIVATE, zero_fd, 0);
611 <    address_space = (char *)mmap(NULL, 1<<24, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
612 <    if ((int)address_space < 0 || (int)good_address_map < 0) {
285 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
286 <                QuitEmulator();
287 <    }
288 <    RAMBaseHost = (uint8 *)mmap(address_space, RAMSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
289 <    ROMBaseHost = (uint8 *)mmap(address_space + 0x00400000, 0x80000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, zero_fd, 0);
290 <        char *nam = tmpnam(NULL);
291 <    int good_address_fd = open(nam, O_CREAT | O_RDWR, 0600);
292 <        char buffer[4096];
293 <    memset(buffer, 1, sizeof(buffer));
294 <    write(good_address_fd, buffer, sizeof(buffer));
295 <    unlink(nam);
296 <    for (int i=0; i<RAMSize; i+=4096)
297 <        mmap(good_address_map + i, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
298 <    for (int i=0; i<0x80000; i+=4096)
299 <        mmap(good_address_map + i + 0x00400000, 4096, PROT_READ, MAP_FIXED | MAP_PRIVATE, good_address_fd, 0);
300 < #else
301 <        RAMBaseHost = new uint8[RAMSize];
302 <        ROMBaseHost = new uint8[0x100000];
608 > #if DIRECT_ADDRESSING
609 >        // RAMBaseMac shall always be zero
610 >        MEMBaseDiff = (uintptr)RAMBaseHost;
611 >        RAMBaseMac = 0;
612 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
613   #endif
614 < #if REAL_ADDRESSING && !EMULATED_68K
615 <        RAMBaseMac = (uint32)RAMBaseHost;
616 <        ROMBaseMac = (uint32)ROMBaseHost;
614 > #if REAL_ADDRESSING
615 >        RAMBaseMac = Host2MacAddr(RAMBaseHost);
616 >        ROMBaseMac = Host2MacAddr(ROMBaseHost);
617   #endif
618          D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac));
619          D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac));
620 <
620 >        
621          // Get rom file path from preferences
622          const char *rom_path = PrefsFindString("rom");
623  
624          // Load Mac ROM
625          int rom_fd = open(rom_path ? rom_path : ROM_FILE_NAME, O_RDONLY);
626          if (rom_fd < 0) {
627 <                ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
627 >                ErrorAlert(STR_NO_ROM_FILE_ERR);
628                  QuitEmulator();
629          }
630          printf(GetString(STR_READING_ROM_FILE));
631          ROMSize = lseek(rom_fd, 0, SEEK_END);
632          if (ROMSize != 64*1024 && ROMSize != 128*1024 && ROMSize != 256*1024 && ROMSize != 512*1024 && ROMSize != 1024*1024) {
633 <                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
633 >                ErrorAlert(STR_ROM_SIZE_ERR);
634                  close(rom_fd);
635                  QuitEmulator();
636          }
637          lseek(rom_fd, 0, SEEK_SET);
638          if (read(rom_fd, ROMBaseHost, ROMSize) != (ssize_t)ROMSize) {
639 <                ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
639 >                ErrorAlert(STR_ROM_FILE_READ_ERR);
640                  close(rom_fd);
641                  QuitEmulator();
642          }
# Line 356 | Line 666 | int main(int argc, char **argv)
666                  printf("WARNING: Cannot detect CPU type, assuming 68020\n");
667                  CPUType = 2;
668          }
669 <        FPUType = 0;    //!!
669 >        FPUType = 1;    // NetBSD has an FPU emulation, so the FPU ought to be available at all times
670          TwentyFourBitAddressing = false;
671   #endif
672  
# Line 365 | Line 675 | int main(int argc, char **argv)
675                  QuitEmulator();
676          D(bug("Initialization complete\n"));
677  
678 + #if !EMULATED_68K
679 +        // (Virtual) supervisor mode, disable interrupts
680 +        EmulatedSR = 0x2700;
681 +
682   #ifdef HAVE_PTHREADS
683          // Get handle of main thread
684          emul_thread = pthread_self();
685   #endif
686  
373 #if !EMULATED_68K
374        // (Virtual) supervisor mode, disable interrupts
375        EmulatedSR = 0x2700;
376
687          // Create and install stack for signal handlers
688          sig_stack = malloc(SIG_STACK_SIZE);
689          D(bug("Signal stack at %p\n", sig_stack));
690          if (sig_stack == NULL) {
691 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
691 >                ErrorAlert(STR_NOT_ENOUGH_MEMORY_ERR);
692                  QuitEmulator();
693          }
694          stack_t new_stack;
# Line 419 | Line 729 | int main(int argc, char **argv)
729   #ifdef ENABLE_MON
730          // Setup SIGINT handler to enter mon
731          sigemptyset(&sigint_sa.sa_mask);
732 <        sigint_sa.sa_handler = sigint_handler;
732 >        sigint_sa.sa_handler = (void (*)(int))sigint_handler;
733          sigint_sa.sa_flags = 0;
734          sigaction(SIGINT, &sigint_sa, NULL);
735   #endif
736  
737 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
737 > #ifndef USE_CPU_EMUL_SERVICES
738 > #if defined(HAVE_PTHREADS)
739 >
740 >        // POSIX threads available, start 60Hz thread
741 >        Set_pthread_attr(&tick_thread_attr, 0);
742 >        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
743 >        if (!tick_thread_active) {
744 >                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
745 >                ErrorAlert(str);
746 >                QuitEmulator();
747 >        }
748 >        D(bug("60Hz thread started\n"));
749 >
750 > #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
751  
752          // POSIX.4 timers and real-time signals available, start 60Hz timer
753          sigemptyset(&timer_sa.sa_mask);
754 <        timer_sa.sa_sigaction = one_tick;
754 >        timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick;
755          timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
756          if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
757                  sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
# Line 455 | Line 778 | int main(int argc, char **argv)
778          }
779          D(bug("60Hz timer started\n"));
780  
458 #elif defined(HAVE_PTHREADS)
459
460        // POSIX threads available, start 60Hz thread
461        pthread_attr_init(&tick_thread_attr);
462 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
463        if (geteuid() == 0) {
464                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
465                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
466                struct sched_param fifo_param;
467                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
468                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
469        }
470 #endif
471        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
472        if (!tick_thread_active) {
473                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
474                ErrorAlert(str);
475                QuitEmulator();
476        }
477        D(bug("60Hz thread started\n"));
478
781   #else
782  
783          // Start 60Hz timer
784          sigemptyset(&timer_sa.sa_mask);         // Block virtual 68k interrupts during SIGARLM handling
785 + #if !EMULATED_68K
786          sigaddset(&timer_sa.sa_mask, SIG_IRQ);
787 + #endif
788          timer_sa.sa_handler = one_tick;
789          timer_sa.sa_flags = SA_ONSTACK | SA_RESTART;
790          if (sigaction(SIGALRM, &timer_sa, NULL) < 0) {
# Line 494 | Line 798 | int main(int argc, char **argv)
798          setitimer(ITIMER_REAL, &req, NULL);
799  
800   #endif
801 + #endif
802  
803 < #ifdef HAVE_PTHREADS
803 > #ifdef USE_PTHREADS_SERVICES
804          // Start XPRAM watchdog thread
805 <        memcpy(last_xpram, XPRAM, 256);
805 >        memcpy(last_xpram, XPRAM, XPRAM_SIZE);
806          xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
807          D(bug("XPRAM thread started\n"));
808   #endif
# Line 524 | Line 829 | void QuitEmulator(void)
829          Exit680x0();
830   #endif
831  
832 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
833 <        // Stop 60Hz timer
834 <        timer_delete(timer);
835 < #elif defined(HAVE_PTHREADS)
832 > #if defined(USE_CPU_EMUL_SERVICES)
833 >        // Show statistics
834 >        uint64 emulated_ticks_end = GetTicks_usec();
835 >        D(bug("%ld ticks in %ld usec = %f ticks/sec [%ld tick checks]\n",
836 >                  (long)emulated_ticks_count, (long)(emulated_ticks_end - emulated_ticks_start),
837 >                  emulated_ticks_count * 1000000.0 / (emulated_ticks_end - emulated_ticks_start), (long)n_check_ticks));
838 > #elif defined(USE_PTHREADS_SERVICES)
839          // Stop 60Hz thread
840          if (tick_thread_active) {
841                  tick_thread_cancel = true;
# Line 536 | Line 844 | void QuitEmulator(void)
844   #endif
845                  pthread_join(tick_thread, NULL);
846          }
847 + #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
848 +        // Stop 60Hz timer
849 +        timer_delete(timer);
850   #else
851          struct itimerval req;
852          req.it_interval.tv_sec = req.it_value.tv_sec = 0;
# Line 543 | Line 854 | void QuitEmulator(void)
854          setitimer(ITIMER_REAL, &req, NULL);
855   #endif
856  
857 < #ifdef HAVE_PTHREADS
857 > #ifdef USE_PTHREADS_SERVICES
858          // Stop XPRAM watchdog thread
859          if (xpram_thread_active) {
860                  xpram_thread_cancel = true;
# Line 557 | Line 868 | void QuitEmulator(void)
868          // Deinitialize everything
869          ExitAll();
870  
871 <        // Delete ROM area
872 <        delete[] ROMBaseHost;
873 <
874 <        // Delete RAM area
875 <        delete[] RAMBaseHost;
871 >        // Free ROM/RAM areas
872 >        if (RAMBaseHost != VM_MAP_FAILED) {
873 >                vm_release(RAMBaseHost, RAMSize + 0x100000);
874 >                RAMBaseHost = NULL;
875 >                ROMBaseHost = NULL;
876 >        }
877  
878 < #if !EMULATED_68K
878 > #if USE_SCRATCHMEM_SUBTERFUGE
879          // Delete scratch memory area
880 <        if (ScratchMem)
881 <                free((void *)(ScratchMem - SCRATCH_MEM_SIZE/2));
880 >        if (ScratchMem != (uint8 *)VM_MAP_FAILED) {
881 >                vm_release((void *)(ScratchMem - SCRATCH_MEM_SIZE/2), SCRATCH_MEM_SIZE);
882 >                ScratchMem = NULL;
883 >        }
884   #endif
885  
886   #if REAL_ADDRESSING
887          // Delete Low Memory area
888          if (lm_area_mapped)
889 <                munmap((char *)0x0000, 0x2000);
889 >                vm_release(0, 0x2000);
890   #endif
891 <
892 <        // Close /dev/zero
893 <        if (zero_fd > 0)
580 <                close(zero_fd);
891 >        
892 >        // Exit VM wrappers
893 >        vm_exit();
894  
895          // Exit system routines
896          SysExit();
# Line 586 | Line 899 | void QuitEmulator(void)
899          PrefsExit();
900  
901          // Close X11 server connection
902 + #ifndef USE_SDL_VIDEO
903          if (x_display)
904                  XCloseDisplay(x_display);
905 + #endif
906 +
907 +        // Notify GUI we are about to leave
908 +        if (gui_connection) {
909 +                if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
910 +                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID);
911 +        }
912  
913          exit(0);
914   }
# Line 600 | Line 921 | void QuitEmulator(void)
921  
922   void FlushCodeCache(void *start, uint32 size)
923   {
924 + #if USE_JIT
925 +    if (UseJIT)
926 +                flush_icache_range((uint8 *)start, size);
927 + #endif
928   #if !EMULATED_68K && defined(__NetBSD__)
929          m68k_sync_icache(start, size);
930   #endif
# Line 617 | Line 942 | static void sigint_handler(...)
942          uaecptr nextpc;
943          extern void m68k_dumpstate(uaecptr *nextpc);
944          m68k_dumpstate(&nextpc);
945 < #else
946 <        char *arg[2] = {"rmon", NULL};
947 <        mon(1, arg);
945 > #endif
946 >        VideoQuitFullScreen();
947 >        char *arg[4] = {"mon", "-m", "-r", NULL};
948 >        mon(3, arg);
949          QuitEmulator();
950 + }
951 + #endif
952 +
953 +
954 + #ifdef HAVE_PTHREADS
955 + /*
956 + *  Pthread configuration
957 + */
958 +
959 + void Set_pthread_attr(pthread_attr_t *attr, int priority)
960 + {
961 +        pthread_attr_init(attr);
962 + #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
963 +        // Some of these only work for superuser
964 +        if (geteuid() == 0) {
965 +                pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
966 +                pthread_attr_setschedpolicy(attr, SCHED_FIFO);
967 +                struct sched_param fifo_param;
968 +                fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
969 +                                              sched_get_priority_max(SCHED_FIFO)) / 2 +
970 +                                             priority);
971 +                pthread_attr_setschedparam(attr, &fifo_param);
972 +        }
973 +        if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
974 + #ifdef PTHREAD_SCOPE_BOUND_NP
975 +            // If system scope is not available (eg. we're not running
976 +            // with CAP_SCHED_MGT capability on an SGI box), try bound
977 +            // scope.  It exposes pthread scheduling to the kernel,
978 +            // without setting realtime priority.
979 +            pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
980   #endif
981 +        }
982 + #endif
983 + }
984 + #endif // HAVE_PTHREADS
985 +
986 +
987 + /*
988 + *  Mutexes
989 + */
990 +
991 + #ifdef HAVE_PTHREADS
992 +
993 + struct B2_mutex {
994 +        B2_mutex() {
995 +            pthread_mutexattr_t attr;
996 +            pthread_mutexattr_init(&attr);
997 +            // Initialize the mutex for priority inheritance --
998 +            // required for accurate timing.
999 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__)
1000 +            pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
1001 + #endif
1002 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
1003 +            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
1004 + #endif
1005 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
1006 +            pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
1007 + #endif
1008 +            pthread_mutex_init(&m, &attr);
1009 +            pthread_mutexattr_destroy(&attr);
1010 +        }
1011 +        ~B2_mutex() {
1012 +            pthread_mutex_trylock(&m); // Make sure it's locked before
1013 +            pthread_mutex_unlock(&m);  // unlocking it.
1014 +            pthread_mutex_destroy(&m);
1015 +        }
1016 +        pthread_mutex_t m;
1017 + };
1018 +
1019 + B2_mutex *B2_create_mutex(void)
1020 + {
1021 +        return new B2_mutex;
1022   }
1023 +
1024 + void B2_lock_mutex(B2_mutex *mutex)
1025 + {
1026 +        pthread_mutex_lock(&mutex->m);
1027 + }
1028 +
1029 + void B2_unlock_mutex(B2_mutex *mutex)
1030 + {
1031 +        pthread_mutex_unlock(&mutex->m);
1032 + }
1033 +
1034 + void B2_delete_mutex(B2_mutex *mutex)
1035 + {
1036 +        delete mutex;
1037 + }
1038 +
1039 + #else
1040 +
1041 + struct B2_mutex {
1042 +        int dummy;
1043 + };
1044 +
1045 + B2_mutex *B2_create_mutex(void)
1046 + {
1047 +        return new B2_mutex;
1048 + }
1049 +
1050 + void B2_lock_mutex(B2_mutex *mutex)
1051 + {
1052 + }
1053 +
1054 + void B2_unlock_mutex(B2_mutex *mutex)
1055 + {
1056 + }
1057 +
1058 + void B2_delete_mutex(B2_mutex *mutex)
1059 + {
1060 +        delete mutex;
1061 + }
1062 +
1063   #endif
1064  
1065  
# Line 635 | Line 1072 | uint32 InterruptFlags = 0;
1072   #if EMULATED_68K
1073   void SetInterruptFlag(uint32 flag)
1074   {
1075 < #ifdef HAVE_PTHREADS
639 <        pthread_mutex_lock(&intflag_lock);
1075 >        LOCK_INTFLAGS;
1076          InterruptFlags |= flag;
1077 <        pthread_mutex_unlock(&intflag_lock);
642 < #else
643 <        InterruptFlags |= flag;         // Pray that this is an atomic operation...
644 < #endif
1077 >        UNLOCK_INTFLAGS;
1078   }
1079  
1080   void ClearInterruptFlag(uint32 flag)
1081   {
1082 < #ifdef HAVE_PTHREADS
650 <        pthread_mutex_lock(&intflag_lock);
651 <        InterruptFlags &= ~flag;
652 <        pthread_mutex_unlock(&intflag_lock);
653 < #else
1082 >        LOCK_INTFLAGS;
1083          InterruptFlags &= ~flag;
1084 < #endif
1084 >        UNLOCK_INTFLAGS;
1085   }
1086   #endif
1087  
# Line 665 | Line 1094 | void TriggerInterrupt(void)
1094          raise(SIG_IRQ);
1095   #endif
1096   }
1097 +
1098 + void TriggerNMI(void)
1099 + {
1100 +        // not yet supported
1101 + }
1102   #endif
1103  
1104  
# Line 674 | Line 1108 | void TriggerInterrupt(void)
1108  
1109   static void xpram_watchdog(void)
1110   {
1111 <        if (memcmp(last_xpram, XPRAM, 256)) {
1112 <                memcpy(last_xpram, XPRAM, 256);
1111 >        if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) {
1112 >                memcpy(last_xpram, XPRAM, XPRAM_SIZE);
1113                  SaveXPRAM();
1114          }
1115   }
1116  
1117 < #ifdef HAVE_PTHREADS
1117 > #ifdef USE_PTHREADS_SERVICES
1118   static void *xpram_func(void *arg)
1119   {
1120          while (!xpram_thread_cancel) {
1121 <                for (int i=0; i<60 && !xpram_thread_cancel; i++) {
1122 < #ifdef HAVE_NANOSLEEP
689 <                        struct timespec req = {1, 0};
690 <                        nanosleep(&req, NULL);
691 < #else
692 <                        usleep(1000000);
693 < #endif
694 <                }
1121 >                for (int i=0; i<60 && !xpram_thread_cancel; i++)
1122 >                        Delay_usec(999999);             // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true
1123                  xpram_watchdog();
1124          }
1125          return NULL;
# Line 708 | Line 1136 | static void one_second(void)
1136          // Pseudo Mac 1Hz interrupt, update local time
1137          WriteMacInt32(0x20c, TimerDateTime());
1138  
1139 < #ifndef HAVE_PTHREADS
1139 >        SetInterruptFlag(INTFLAG_1HZ);
1140 >        TriggerInterrupt();
1141 >
1142 > #ifndef USE_PTHREADS_SERVICES
1143          static int second_counter = 0;
1144          if (++second_counter > 60) {
1145                  second_counter = 0;
# Line 725 | Line 1156 | static void one_tick(...)
1156                  one_second();
1157          }
1158  
1159 < #ifndef HAVE_PTHREADS
1160 <        // No threads available, perform video refresh from here
1159 > #ifndef USE_PTHREADS_SERVICES
1160 >        // Threads not used to trigger interrupts, perform video refresh from here
1161          VideoRefresh();
1162   #endif
1163  
1164 + #ifndef HAVE_PTHREADS
1165 +        // No threads available, perform networking from here
1166 +        SetInterruptFlag(INTFLAG_ETHER);
1167 + #endif
1168 +
1169          // Trigger 60Hz interrupt
1170          if (ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted()) {
1171                  SetInterruptFlag(INTFLAG_60HZ);
# Line 737 | Line 1173 | static void one_tick(...)
1173          }
1174   }
1175  
1176 < #ifdef HAVE_PTHREADS
1176 > #ifdef USE_PTHREADS_SERVICES
1177   static void *tick_func(void *arg)
1178   {
1179 +        uint64 start = GetTicks_usec();
1180 +        int64 ticks = 0;
1181 +        uint64 next = GetTicks_usec();
1182          while (!tick_thread_cancel) {
744
745                // Wait
746 #ifdef HAVE_NANOSLEEP
747                struct timespec req = {0, 16625000};
748                nanosleep(&req, NULL);
749 #else
750                usleep(16625);
751 #endif
752
753                // Action
1183                  one_tick();
1184 +                next += 16625;
1185 +                int64 delay = next - GetTicks_usec();
1186 +                if (delay > 0)
1187 +                        Delay_usec(delay);
1188 +                else if (delay < -16625)
1189 +                        next = GetTicks_usec();
1190 +                ticks++;
1191          }
1192 +        uint64 end = GetTicks_usec();
1193 +        D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1194          return NULL;
1195   }
1196   #endif
# Line 808 | Line 1246 | static void sigill_handler(int sig, int
1246  
1247   #define STORE_SR(v) \
1248          scp->sc_ps = (v) & 0xff; \
1249 <        EmulatedSR = (v) & 0x2700; \
1249 >        EmulatedSR = (v) & 0xe700; \
1250          if (((v) & 0x0700) == 0 && InterruptFlags) \
1251                  TriggerInterrupt();
1252  
# Line 871 | Line 1309 | static void sigill_handler(int sig, int
1309                  case 0x007c: {  // ori #xxxx,sr
1310                          uint16 sr = GET_SR | pc[1];
1311                          scp->sc_ps = sr & 0xff;         // oring bits into the sr can't enable interrupts, so we don't need to call STORE_SR
1312 <                        EmulatedSR = sr & 0x2700;
1312 >                        EmulatedSR = sr & 0xe700;
1313                          INC_PC(4);
1314                          break;
1315                  }
# Line 948 | Line 1386 | static void sigill_handler(int sig, int
1386                  }
1387  
1388                  case 0xf327:    // fsave -(sp)
1389 <                        goto ill;       //!!
1389 >                        regs->a[7] -= 4;
1390 >                        WriteMacInt32(regs->a[7], 0x41000000);  // Idle frame
1391 >                        scp->sc_sp = regs->a[7];
1392 >                        INC_PC(2);
1393 >                        break;
1394  
1395                  case 0xf35f:    // frestore (sp)+
1396 <                        goto ill;       //!!
1396 >                        regs->a[7] += 4;
1397 >                        scp->sc_sp = regs->a[7];
1398 >                        INC_PC(2);
1399 >                        break;
1400  
1401 <                case 0x4e73: {  // rte (only handles format 0)
1401 >                case 0x4e73: {  // rte
1402                          uint32 a7 = regs->a[7];
1403                          uint16 sr = ReadMacInt16(a7);
1404                          a7 += 2;
1405                          scp->sc_ps = sr & 0xff;
1406 <                        EmulatedSR = sr & 0x2700;
1406 >                        EmulatedSR = sr & 0xe700;
1407                          scp->sc_pc = ReadMacInt32(a7);
1408 <                        a7 += 6;
1409 <                        scp->sc_sp = regs->a[7] = a7;
1408 >                        a7 += 4;
1409 >                        uint16 format = ReadMacInt16(a7) >> 12;
1410 >                        a7 += 2;
1411 >                        static const int frame_adj[16] = {
1412 >                                0, 0, 4, 4, 8, 0, 0, 52, 50, 12, 24, 84, 16, 0, 0, 0
1413 >                        };
1414 >                        scp->sc_sp = regs->a[7] = a7 + frame_adj[format];
1415                          break;
1416                  }
1417  
1418                  case 0x4e7a:    // movec cr,x
1419                          switch (pc[1]) {
970                                case 0x8801:    // movec vbr,a0
971                                        regs->a[0] = 0;
972                                        break;
973                                case 0x9801:    // movec vbr,a1
974                                        regs->a[1] = 0;
975                                        break;
1420                                  case 0x0002:    // movec cacr,d0
1421                                          regs->d[0] = 0x3111;
1422                                          break;
# Line 980 | Line 1424 | static void sigill_handler(int sig, int
1424                                          regs->d[1] = 0x3111;
1425                                          break;
1426                                  case 0x0003:    // movec tc,d0
1427 +                                case 0x0004:    // movec itt0,d0
1428 +                                case 0x0005:    // movec itt1,d0
1429 +                                case 0x0006:    // movec dtt0,d0
1430 +                                case 0x0007:    // movec dtt1,d0
1431 +                                case 0x0806:    // movec urp,d0
1432 +                                case 0x0807:    // movec srp,d0
1433                                          regs->d[0] = 0;
1434                                          break;
1435 +                                case 0x1000:    // movec sfc,d1
1436 +                                case 0x1001:    // movec dfc,d1
1437                                  case 0x1003:    // movec tc,d1
1438 +                                case 0x1801:    // movec vbr,d1
1439                                          regs->d[1] = 0;
1440                                          break;
1441 +                                case 0x8801:    // movec vbr,a0
1442 +                                        regs->a[0] = 0;
1443 +                                        break;
1444 +                                case 0x9801:    // movec vbr,a1
1445 +                                        regs->a[1] = 0;
1446 +                                        break;
1447                                  default:
1448                                          goto ill;
1449                          }
# Line 993 | Line 1452 | static void sigill_handler(int sig, int
1452  
1453                  case 0x4e7b:    // movec x,cr
1454                          switch (pc[1]) {
1455 +                                case 0x1000:    // movec d1,sfc
1456 +                                case 0x1001:    // movec d1,dfc
1457                                  case 0x0801:    // movec d0,vbr
1458 +                                case 0x1801:    // movec d1,vbr
1459                                          break;
1460                                  case 0x0002:    // movec d0,cacr
1461                                  case 0x1002:    // movec d1,cacr
# Line 1027 | Line 1489 | ill:           printf("SIGILL num %d, code %d\n",
1489                          for (int i=0; i<8; i++)
1490                                  printf("  a%d %08x\n", i, state->ss_frame.f_regs[i+8]);
1491  
1492 +                        VideoQuitFullScreen();
1493   #ifdef ENABLE_MON
1494 <                        char *arg[2] = {"rmon", NULL};
1495 <                        mon(1, arg);
1494 >                        char *arg[4] = {"mon", "-m", "-r", NULL};
1495 >                        mon(3, arg);
1496   #endif
1497                          QuitEmulator();
1498                          break;
# Line 1087 | Line 1550 | void display_alert(int title_id, int pre
1550  
1551   void ErrorAlert(const char *text)
1552   {
1553 < #ifdef ENABLE_GTK
1553 >        if (gui_connection) {
1554 >                if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
1555 >                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
1556 >                        return;
1557 >        }
1558 > #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1559          if (PrefsFindBool("nogui") || x_display == NULL) {
1560                  printf(GetString(STR_SHELL_ERROR_PREFIX), text);
1561                  return;
# Line 1106 | Line 1574 | void ErrorAlert(const char *text)
1574  
1575   void WarningAlert(const char *text)
1576   {
1577 < #ifdef ENABLE_GTK
1577 >        if (gui_connection) {
1578 >                if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR &&
1579 >                        rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR)
1580 >                        return;
1581 >        }
1582 > #if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO)
1583          if (PrefsFindBool("nogui") || x_display == NULL) {
1584                  printf(GetString(STR_SHELL_WARNING_PREFIX), text);
1585                  return;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines