ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/BeOS/main_beos.cpp
Revision: 1.2
Committed: 2002-04-21T15:07:08Z (22 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.1: +5 -72 lines
Log Message:
Add support to decode parcels-based ROMs
- include/rom_patches.h (DecodeROM): Declare.
- rom_patches.cpp (DecodeROM): Define.
- Unix/main_unix.cpp, BeOS/main_beos.cpp (decode_lzss): Move to...
- rom_patches.cpp (decode_lzss): ... here.
- Unix/main_unix.cpp (main): Call DecodeROM().
- BeOS/main_beos.cpp (SheepShaver::load_rom): Call DecodeROM().

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * main_beos.cpp - Emulation core, BeOS implementation
3     *
4     * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     /*
22     * NOTES:
23     *
24     * SheepShaver uses three run-time environments, reflected by the value of XLM_RUN_MODE.
25     * The two modes which are also present in the original MacOS, are:
26     * MODE_68K - 68k emulator is active
27     * MODE_NATIVE - 68k emulator is inactive
28     * In the original MacOS, these two modes have different memory mappings and exception
29     * tables. Under SheepShaver, the only difference is the handling of interrupts (see below).
30     * SheepShaver extends the 68k emulator with special opcodes (EMUL_OP) to perform faster
31     * mode switches when patching 68k routines with PowerPC code and adds a third run mode:
32     * MODE_EMUL_OP - 68k emulator active, but native register usage
33     *
34     * Switches between MODE_68K and MODE_NATIVE are only done with the Mixed Mode Manager
35     * (via nanokernel patches). The switch from MODE_68K to MODE_EMUL_OP occurs when executin
36     * one of the EMUL_OP 68k opcodes. When the opcode routine is done, it returns to MODE_68K.
37     *
38     * The Execute68k() routine allows EMUL_OP routines to execute 68k subroutines. It switches
39     * from MODE_EMUL_OP back to MODE_68K, so it must not be used by native routines (executing
40     * in MODE_NATIVE) nor by any other thread than the emul_thread (because the 68k emulator
41     * is not reentrant). When the 68k subroutine returns, it switches back to MODE_EMUL_OP.
42     * It is OK for a 68k routine called with Execute68k() to contain an EMUL_OP opcode.
43     *
44     * The handling of interrupts depends on the current run mode:
45     * MODE_68K - The USR1 signal handler sets one bit in the processor's CR. The 68k emulator
46     * will then execute the 68k interrupt routine when fetching the next instruction.
47     * MODE_NATIVE - The USR1 signal handler switches back to the original stack (signals run
48     * on a separate signal stack) and enters the External Interrupt routine in the
49     * nanokernel.
50     * MODE_EMUL_OP - The USR1 signal handler directly executes the 68k interrupt routine
51     * with Execute68k(). Before doing this, it must first check the current 68k interrupt
52     * level which is stored in XLM_68K_R25. This variable is set to the current level
53     * when entering EMUL_OP mode. Execute68k() also uses it to restore the level so that
54     * Execute68k()'d routines will run at the same interrupt level as the EMUL_OP routine
55     * it was called from.
56     */
57    
58     #include <Path.h>
59     #include <unistd.h>
60     #include <signal.h>
61     #include <stdio.h>
62     #include <stdlib.h>
63     #include <string.h>
64     #include <time.h>
65    
66     #include "sysdeps.h"
67     #include "main.h"
68     #include "version.h"
69     #include "prefs.h"
70     #include "prefs_editor.h"
71     #include "cpu_emulation.h"
72     #include "emul_op.h"
73     #include "xlowmem.h"
74     #include "xpram.h"
75     #include "timer.h"
76     #include "adb.h"
77     #include "sony.h"
78     #include "disk.h"
79     #include "cdrom.h"
80     #include "scsi.h"
81     #include "video.h"
82     #include "audio.h"
83     #include "ether.h"
84     #include "serial.h"
85     #include "clip.h"
86     #include "extfs.h"
87     #include "sys.h"
88     #include "macos_util.h"
89     #include "rom_patches.h"
90     #include "user_strings.h"
91    
92     #include "sheep_driver.h"
93    
94     #define DEBUG 0
95     #include "debug.h"
96    
97     // Enable Execute68k() safety checks?
98     #define SAFE_EXEC_68K 0
99    
100     // Save FP regs in Execute68k()?
101     #define SAVE_FP_EXEC_68K 0
102    
103     // Interrupts in EMUL_OP mode?
104     #define INTERRUPTS_IN_EMUL_OP_MODE 1
105    
106     // Interrupts in native mode?
107     #define INTERRUPTS_IN_NATIVE_MODE 1
108    
109    
110     // Constants
111     const char APP_SIGNATURE[] = "application/x-vnd.cebix-SheepShaver";
112     const char ROM_FILE_NAME[] = "ROM";
113     const char ROM_FILE_NAME2[] = "Mac OS ROM";
114     const char KERNEL_AREA_NAME[] = "Macintosh Kernel Data";
115     const char KERNEL_AREA2_NAME[] = "Macintosh Kernel Data 2";
116     const char RAM_AREA_NAME[] = "Macintosh RAM";
117     const char ROM_AREA_NAME[] = "Macintosh ROM";
118     const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache";
119    
120     const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area
121    
122     const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data
123     const uint32 KERNEL_DATA2_BASE = 0x5fffe000;// Alternate address of Kernel Data
124     const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area
125    
126     const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack
127    
128     const uint32 MSG_START = 'strt'; // Emulator start message
129    
130    
131     // Emulator Data
132     struct EmulatorData {
133     uint32 v[0x400];
134     };
135    
136    
137     // Kernel Data
138     struct KernelData {
139     uint32 v[0x400];
140     EmulatorData ed;
141     };
142    
143    
144     // Application object
145     class SheepShaver : public BApplication {
146     public:
147     SheepShaver() : BApplication(APP_SIGNATURE)
148     {
149     // Find application directory and cwd to it
150     app_info the_info;
151     GetAppInfo(&the_info);
152     BEntry the_file(&the_info.ref);
153     BEntry the_dir;
154     the_file.GetParent(&the_dir);
155     BPath the_path;
156     the_dir.GetPath(&the_path);
157     chdir(the_path.Path());
158    
159     // Initialize other variables
160     sheep_fd = -1;
161     emulator_data = NULL;
162     kernel_area = kernel_area2 = rom_area = ram_area = dr_cache_area = -1;
163     emul_thread = nvram_thread = tick_thread = -1;
164     ReadyForSignals = false;
165     AllowQuitting = true;
166     NVRAMThreadActive = true;
167     TickThreadActive = true;
168     memset(last_xpram, 0, XPRAM_SIZE);
169     }
170     virtual void ReadyToRun(void);
171     virtual void MessageReceived(BMessage *msg);
172     void StartEmulator(void);
173     virtual bool QuitRequested(void);
174     virtual void Quit(void);
175    
176     thread_id emul_thread; // Emulator thread
177     thread_id nvram_thread; // NVRAM watchdog thread
178     thread_id tick_thread; // 60Hz thread
179    
180     KernelData *kernel_data; // Pointer to Kernel Data
181     EmulatorData *emulator_data;
182    
183     bool ReadyForSignals; // Flag: emul_thread ready to receive signals
184     bool AllowQuitting; // Flag: Alt-Q quitting allowed
185     bool NVRAMThreadActive; // nvram_thread will exit when this is false
186     bool TickThreadActive; // tick_thread will exit when this is false
187    
188     uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
189    
190     private:
191     static status_t emul_func(void *arg);
192     static status_t nvram_func(void *arg);
193     static status_t tick_func(void *arg);
194     static void sigusr1_invoc(int sig, void *arg, vregs *r);
195     void sigusr1_handler(vregs *r);
196     static void sigsegv_invoc(int sig, void *arg, vregs *r);
197     static void sigill_invoc(int sig, void *arg, vregs *r);
198     void jump_to_rom(uint32 entry);
199    
200     void init_rom(void);
201     void load_rom(void);
202    
203     int sheep_fd; // FD of sheep driver
204    
205     area_id kernel_area; // Kernel Data area ID
206     area_id kernel_area2; // Alternate Kernel Data area ID
207     area_id rom_area; // ROM area ID
208     area_id ram_area; // RAM area ID
209     area_id dr_cache_area; // DR Cache area ID
210    
211     struct sigaction sigusr1_action; // Interrupt signal (of emulator thread)
212     struct sigaction sigsegv_action; // Data access exception signal (of emulator thread)
213     struct sigaction sigill_action; // Illegal instruction exception signal (of emulator thread)
214    
215     // Exceptions
216     class area_error {};
217     class file_open_error {};
218     class file_read_error {};
219     class rom_size_error {};
220     };
221    
222    
223     // Global variables
224     SheepShaver *the_app; // Pointer to application object
225     #if !EMULATED_PPC
226     void *TOC; // TOC pointer
227     #endif
228     uint32 RAMBase; // Base address of Mac RAM
229     uint32 RAMSize; // Size of Mac RAM
230     uint32 KernelDataAddr; // Address of Kernel Data
231     uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
232     uint32 DRCacheAddr; // Address of DR Cache
233     uint32 PVR; // Theoretical PVR
234     int64 CPUClockSpeed; // Processor clock speed (Hz)
235     int64 BusClockSpeed; // Bus clock speed (Hz)
236     system_info SysInfo; // System information
237    
238     static void *sig_stack = NULL; // Stack for signal handlers
239     static void *extra_stack = NULL; // Stack for SIGSEGV inside interrupt handler
240    
241    
242     // Prototypes
243     static void sigsegv_handler(vregs *r);
244     static void sigill_handler(vregs *r);
245    
246    
247     /*
248     * Create application object and start it
249     */
250    
251     int main(int argc, char **argv)
252     {
253     tzset();
254     the_app = new SheepShaver();
255     the_app->Run();
256     delete the_app;
257     return 0;
258     }
259    
260    
261     /*
262     * Run application
263     */
264    
265     #if !EMULATED_PPC
266     static asm void *get_toc(void)
267     {
268     mr r3,r2
269     blr
270     }
271     #endif
272    
273     void SheepShaver::ReadyToRun(void)
274     {
275     // Print some info
276     printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR);
277     printf(" %s\n", GetString(STR_ABOUT_TEXT2));
278    
279     #if !EMULATED_PPC
280     // Get TOC pointer
281     TOC = get_toc();
282     #endif
283    
284     // Get system info
285     get_system_info(&SysInfo);
286     switch (SysInfo.cpu_type) {
287     case B_CPU_PPC_601:
288     PVR = 0x00010000;
289     break;
290     case B_CPU_PPC_603:
291     PVR = 0x00030000;
292     break;
293     case B_CPU_PPC_603e:
294     PVR = 0x00060000;
295     break;
296     case B_CPU_PPC_604:
297     PVR = 0x00040000;
298     break;
299     case B_CPU_PPC_604e:
300     PVR = 0x00090000;
301     break;
302     case B_CPU_PPC_750:
303     PVR = 0x00080000;
304     break;
305     default:
306     PVR = 0x00040000;
307     break;
308     }
309     CPUClockSpeed = SysInfo.cpu_clock_speed;
310     BusClockSpeed = SysInfo.bus_clock_speed;
311    
312     // Delete old areas
313     area_id old_kernel_area = find_area(KERNEL_AREA_NAME);
314     if (old_kernel_area > 0)
315     delete_area(old_kernel_area);
316     area_id old_kernel2_area = find_area(KERNEL_AREA2_NAME);
317     if (old_kernel2_area > 0)
318     delete_area(old_kernel2_area);
319     area_id old_ram_area = find_area(RAM_AREA_NAME);
320     if (old_ram_area > 0)
321     delete_area(old_ram_area);
322     area_id old_rom_area = find_area(ROM_AREA_NAME);
323     if (old_rom_area > 0)
324     delete_area(old_rom_area);
325     area_id old_dr_cache_area = find_area(DR_CACHE_AREA_NAME);
326     if (old_dr_cache_area > 0)
327     delete_area(old_dr_cache_area);
328    
329     // Read preferences
330     int argc = 0;
331     char **argv = NULL;
332     PrefsInit(argc, argv);
333    
334     // Init system routines
335     SysInit();
336    
337     // Test amount of RAM available for areas
338     if (SysInfo.max_pages * B_PAGE_SIZE < 16 * 1024 * 1024) {
339     ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
340     PostMessage(B_QUIT_REQUESTED);
341     return;
342     }
343    
344     // Show preferences editor (or start emulator directly)
345     if (!PrefsFindBool("nogui"))
346     PrefsEditor(MSG_START);
347     else
348     PostMessage(MSG_START);
349     }
350    
351    
352     /*
353     * Message received
354     */
355    
356     void SheepShaver::MessageReceived(BMessage *msg)
357     {
358     switch (msg->what) {
359     case MSG_START:
360     StartEmulator();
361     break;
362     default:
363     BApplication::MessageReceived(msg);
364     }
365     }
366    
367    
368     /*
369     * Start emulator
370     */
371    
372     void SheepShaver::StartEmulator(void)
373     {
374     char str[256];
375    
376     // Open sheep driver and remap low memory
377     sheep_fd = open("/dev/sheep", 0);
378     if (sheep_fd < 0) {
379     sprintf(str, GetString(STR_NO_SHEEP_DRIVER_ERR), strerror(sheep_fd), sheep_fd);
380     ErrorAlert(str);
381     PostMessage(B_QUIT_REQUESTED);
382     return;
383     }
384     status_t res = ioctl(sheep_fd, SHEEP_UP);
385     if (res < 0) {
386     sprintf(str, GetString(STR_SHEEP_UP_ERR), strerror(res), res);
387     ErrorAlert(str);
388     PostMessage(B_QUIT_REQUESTED);
389     return;
390     }
391    
392     // Create areas for Kernel Data
393     kernel_data = (KernelData *)KERNEL_DATA_BASE;
394     kernel_area = create_area(KERNEL_AREA_NAME, &kernel_data, B_EXACT_ADDRESS, KERNEL_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
395     if (kernel_area < 0) {
396     sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(kernel_area), kernel_area);
397     ErrorAlert(str);
398     PostMessage(B_QUIT_REQUESTED);
399     return;
400     }
401     emulator_data = &kernel_data->ed;
402     KernelDataAddr = (uint32)kernel_data;
403     D(bug("Kernel Data area %ld at %p, Emulator Data at %p\n", kernel_area, kernel_data, emulator_data));
404    
405     void *kernel_data2 = (void *)KERNEL_DATA2_BASE;
406     kernel_area2 = clone_area(KERNEL_AREA2_NAME, &kernel_data2, B_EXACT_ADDRESS, B_READ_AREA | B_WRITE_AREA, kernel_area);
407     if (kernel_area2 < 0) {
408     sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(kernel_area2), kernel_area2);
409     ErrorAlert(str);
410     PostMessage(B_QUIT_REQUESTED);
411     return;
412     }
413     D(bug("Kernel Data 2 area %ld at %p\n", kernel_area2, kernel_data2));
414    
415     // Create area for Mac RAM
416     RAMSize = PrefsFindInt32("ramsize") & 0xfff00000; // Round down to 1MB boundary
417     if (RAMSize < 8*1024*1024) {
418     WarningAlert(GetString(STR_SMALL_RAM_WARN));
419     RAMSize = 8*1024*1024;
420     }
421    
422     RAMBase = 0x10000000;
423     ram_area = create_area(RAM_AREA_NAME, (void **)&RAMBase, B_BASE_ADDRESS, RAMSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
424     if (ram_area < 0) {
425     sprintf(str, GetString(STR_NO_RAM_AREA_ERR), strerror(ram_area), ram_area);
426     ErrorAlert(str);
427     PostMessage(B_QUIT_REQUESTED);
428     return;
429     }
430     D(bug("RAM area %ld at %p\n", ram_area, RAMBase));
431    
432     // Create area and load Mac ROM
433     try {
434     init_rom();
435     } catch (area_error) {
436     ErrorAlert(GetString(STR_NO_ROM_AREA_ERR));
437     PostMessage(B_QUIT_REQUESTED);
438     return;
439     } catch (file_open_error) {
440     ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
441     PostMessage(B_QUIT_REQUESTED);
442     return;
443     } catch (file_read_error) {
444     ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
445     PostMessage(B_QUIT_REQUESTED);
446     return;
447     } catch (rom_size_error) {
448     ErrorAlert(GetString(STR_ROM_SIZE_ERR));
449     PostMessage(B_QUIT_REQUESTED);
450     return;
451     }
452    
453     // Create area for DR Cache
454     DRCacheAddr = DR_CACHE_BASE;
455     dr_cache_area = create_area(DR_CACHE_AREA_NAME, (void **)&DRCacheAddr, B_EXACT_ADDRESS, DR_CACHE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
456     if (dr_cache_area < 0) {
457     sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_cache_area), dr_cache_area);
458     ErrorAlert(str);
459     PostMessage(B_QUIT_REQUESTED);
460     return;
461     }
462     D(bug("DR Cache area %ld at %p\n", dr_cache_area, DRCacheAddr));
463    
464     // Load NVRAM
465     XPRAMInit();
466    
467     // Set boot volume
468     drive = PrefsFindInt32("bootdrive");
469     XPRAM[0x1378] = i16 >> 8;
470     XPRAM[0x1379] = i16 & 0xff;
471     driver = PrefsFindInt32("bootdriver");
472     XPRAM[0x137a] = i16 >> 8;
473     XPRAM[0x137b] = i16 & 0xff;
474    
475     // Create BootGlobs at top of Mac memory
476     memset((void *)(RAMBase + RAMSize - 4096), 0, 4096);
477     BootGlobsAddr = RAMBase + RAMSize - 0x1c;
478     uint32 *boot_globs = (uint32 *)BootGlobsAddr;
479     boot_globs[-5] = htonl(RAMBase + RAMSize); // MemTop
480     boot_globs[0] = htonl(RAMBase); // First RAM bank
481     boot_globs[1] = htonl(RAMSize);
482     boot_globs[2] = htonl((uint32)-1); // End of bank table
483    
484     // Init drivers
485     SonyInit();
486     DiskInit();
487     CDROMInit();
488     SCSIInit();
489    
490     // Init external file system
491     ExtFSInit();
492    
493     // Init audio
494     AudioInit();
495    
496     // Init network
497     EtherInit();
498    
499     // Init serial ports
500     SerialInit();
501    
502     // Init Time Manager
503     TimerInit();
504    
505     // Init clipboard
506     ClipInit();
507    
508     // Init video
509     if (!VideoInit()) {
510     PostMessage(B_QUIT_REQUESTED);
511     return;
512     }
513    
514     // Install ROM patches
515     if (!PatchROM()) {
516     ErrorAlert(GetString(STR_UNSUPPORTED_ROM_TYPE_ERR));
517     PostMessage(B_QUIT_REQUESTED);
518     return;
519     }
520    
521     // Clear caches (as we loaded and patched code) and write protect ROM
522     #if !EMULATED_PPC
523     clear_caches((void *)ROM_BASE, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE);
524     #endif
525     set_area_protection(rom_area, B_READ_AREA);
526    
527     // Initialize Kernel Data
528     memset(kernel_data, 0, sizeof(KernelData));
529     if (ROMType == ROMTYPE_NEWWORLD) {
530     static uint32 of_dev_tree[4] = {0, 0, 0, 0};
531     static uint8 vector_lookup_tbl[128];
532     static uint8 vector_mask_tbl[64];
533     memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80);
534     memset(vector_lookup_tbl, 0, 128);
535     memset(vector_mask_tbl, 0, 64);
536     kernel_data->v[0xb80 >> 2] = htonl(ROM_BASE);
537     kernel_data->v[0xb84 >> 2] = htonl((uint32)of_dev_tree); // OF device tree base
538     kernel_data->v[0xb90 >> 2] = htonl((uint32)vector_lookup_tbl);
539     kernel_data->v[0xb94 >> 2] = htonl((uint32)vector_mask_tbl);
540     kernel_data->v[0xb98 >> 2] = htonl(ROM_BASE); // OpenPIC base
541     kernel_data->v[0xbb0 >> 2] = htonl(0); // ADB base
542     kernel_data->v[0xc20 >> 2] = htonl(RAMSize);
543     kernel_data->v[0xc24 >> 2] = htonl(RAMSize);
544     kernel_data->v[0xc30 >> 2] = htonl(RAMSize);
545     kernel_data->v[0xc34 >> 2] = htonl(RAMSize);
546     kernel_data->v[0xc38 >> 2] = htonl(0x00010020);
547     kernel_data->v[0xc3c >> 2] = htonl(0x00200001);
548     kernel_data->v[0xc40 >> 2] = htonl(0x00010000);
549     kernel_data->v[0xc50 >> 2] = htonl(RAMBase);
550     kernel_data->v[0xc54 >> 2] = htonl(RAMSize);
551     kernel_data->v[0xf60 >> 2] = htonl(PVR);
552     kernel_data->v[0xf64 >> 2] = htonl(CPUClockSpeed);
553     kernel_data->v[0xf68 >> 2] = htonl(BusClockSpeed);
554     kernel_data->v[0xf6c >> 2] = htonl(CPUClockSpeed);
555     } else {
556     kernel_data->v[0xc80 >> 2] = htonl(RAMSize);
557     kernel_data->v[0xc84 >> 2] = htonl(RAMSize);
558     kernel_data->v[0xc90 >> 2] = htonl(RAMSize);
559     kernel_data->v[0xc94 >> 2] = htonl(RAMSize);
560     kernel_data->v[0xc98 >> 2] = htonl(0x00010020);
561     kernel_data->v[0xc9c >> 2] = htonl(0x00200001);
562     kernel_data->v[0xca0 >> 2] = htonl(0x00010000);
563     kernel_data->v[0xcb0 >> 2] = htonl(RAMBase);
564     kernel_data->v[0xcb4 >> 2] = htonl(RAMSize);
565     kernel_data->v[0xf80 >> 2] = htonl(PVR);
566     kernel_data->v[0xf84 >> 2] = htonl(CPUClockSpeed);
567     kernel_data->v[0xf88 >> 2] = htonl(BusClockSpeed);
568     kernel_data->v[0xf8c >> 2] = htonl(CPUClockSpeed);
569     }
570    
571     // Initialize extra low memory
572     D(bug("Initializing Low Memory...\n"));
573     memset(NULL, 0, 0x3000);
574     WriteMacInt32(XLM_SIGNATURE, 'Baah'); // Signature to detect SheepShaver
575     WriteMacInt32(XLM_KERNEL_DATA, (uint32)kernel_data); // For trap replacement routines
576     WriteMacInt32(XLM_SHEEP_OBJ, (uint32)this); // Pointer to SheepShaver object
577     WriteMacInt32(XLM_PVR, PVR); // Theoretical PVR
578     WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed); // For DriverServicesLib patch
579     WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
580     #if !EMULATED_PPC
581     WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator
582     WriteMacInt32(XLM_ETHER_INIT, *(uint32 *)InitStreamModule); // DLPI ethernet driver functions
583     WriteMacInt32(XLM_ETHER_TERM, *(uint32 *)TerminateStreamModule);
584     WriteMacInt32(XLM_ETHER_OPEN, *(uint32 *)ether_open);
585     WriteMacInt32(XLM_ETHER_CLOSE, *(uint32 *)ether_close);
586     WriteMacInt32(XLM_ETHER_WPUT, *(uint32 *)ether_wput);
587     WriteMacInt32(XLM_ETHER_RSRV, *(uint32 *)ether_rsrv);
588     WriteMacInt32(XLM_VIDEO_DOIO, *(uint32 *)VideoDoDriverIO);
589     #endif
590     D(bug("Low Memory initialized\n"));
591    
592     // Disallow quitting with Alt-Q from now on
593     AllowQuitting = false;
594    
595     // Start 60Hz interrupt
596     tick_thread = spawn_thread(tick_func, "60Hz", B_URGENT_DISPLAY_PRIORITY, this);
597     resume_thread(tick_thread);
598    
599     // Start NVRAM watchdog thread
600     memcpy(last_xpram, XPRAM, XPRAM_SIZE);
601     nvram_thread = spawn_thread(nvram_func, "NVRAM Watchdog", B_LOW_PRIORITY, this);
602     resume_thread(nvram_thread);
603    
604     // Start emulator thread
605     emul_thread = spawn_thread(emul_func, "MacOS", B_NORMAL_PRIORITY, this);
606     resume_thread(emul_thread);
607     }
608    
609    
610     /*
611     * Quit requested
612     */
613    
614     bool SheepShaver::QuitRequested(void)
615     {
616     if (AllowQuitting)
617     return BApplication::QuitRequested();
618     else
619     return false;
620     }
621    
622     void SheepShaver::Quit(void)
623     {
624     status_t l;
625    
626     // Stop 60Hz interrupt
627     if (tick_thread > 0) {
628     TickThreadActive = false;
629     wait_for_thread(tick_thread, &l);
630     }
631    
632     // Stop NVRAM watchdog
633     if (nvram_thread > 0) {
634     status_t l;
635     NVRAMThreadActive = false;
636     suspend_thread(nvram_thread); // Wake thread up from snooze()
637     snooze(1000);
638     resume_thread(nvram_thread);
639     while (wait_for_thread(nvram_thread, &l) == B_INTERRUPTED) ;
640     }
641    
642     // Wait for emulator thread to finish
643     if (emul_thread > 0)
644     wait_for_thread(emul_thread, &l);
645    
646     // Save NVRAM
647     XPRAMExit();
648    
649     // Exit clipboard
650     ClipExit();
651    
652     // Exit Time Manager
653     TimerExit();
654    
655     // Exit serial
656     SerialExit();
657    
658     // Exit network
659     EtherExit();
660    
661     // Exit audio
662     AudioExit();
663    
664     // Exit video
665     VideoExit();
666    
667     // Exit external file system
668     ExtFSExit();
669    
670     // Exit drivers
671     SCSIExit();
672     CDROMExit();
673     DiskExit();
674     SonyExit();
675    
676     // Delete DR Cache area
677     if (dr_cache_area >= 0)
678     delete_area(dr_cache_area);
679    
680     // Delete ROM area
681     if (rom_area >= 0)
682     delete_area(rom_area);
683    
684     // Delete RAM area
685     if (ram_area >= 0)
686     delete_area(ram_area);
687    
688     // Delete Kernel Data area2
689     if (kernel_area2 >= 0)
690     delete_area(kernel_area2);
691     if (kernel_area >= 0)
692     delete_area(kernel_area);
693    
694     // Unmap low memory and close sheep driver
695     if (sheep_fd >= 0) {
696     ioctl(sheep_fd, SHEEP_DOWN);
697     close(sheep_fd);
698     }
699    
700     // Exit system routines
701     SysExit();
702    
703     // Exit preferences
704     PrefsExit();
705    
706     BApplication::Quit();
707     }
708    
709    
710     /*
711     * Create area for ROM (sets rom_area) and load ROM file
712     *
713     * area_error : Cannot create area
714     * file_open_error: Cannot open ROM file
715     * file_read_error: Cannot read ROM file
716     */
717    
718     void SheepShaver::init_rom(void)
719     {
720     // Create area for ROM
721     void *rom_addr = (void *)ROM_BASE;
722     rom_area = create_area(ROM_AREA_NAME, &rom_addr, B_EXACT_ADDRESS, ROM_AREA_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
723     if (rom_area < 0)
724     throw area_error();
725     D(bug("ROM area %ld at %p\n", rom_area, rom_addr));
726    
727     // Load ROM
728     load_rom();
729     }
730    
731    
732     /*
733     * Load ROM file
734     *
735     * file_open_error: Cannot open ROM file (nor use built-in ROM)
736     * file_read_error: Cannot read ROM file
737     */
738    
739     void SheepShaver::load_rom(void)
740     {
741     // Get rom file path from preferences
742     const char *rom_path = PrefsFindString("rom");
743    
744     // Try to open ROM file
745     BFile file(rom_path ? rom_path : ROM_FILE_NAME, B_READ_ONLY);
746     if (file.InitCheck() != B_NO_ERROR) {
747    
748     // Failed, then ask memory_mess driver for ROM
749     uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work
750     ssize_t actual = read(sheep_fd, (void *)rom, ROM_SIZE);
751     if (actual == ROM_SIZE) {
752     memcpy((void *)ROM_BASE, rom, ROM_SIZE);
753     delete[] rom;
754     return;
755     } else
756     throw file_open_error();
757     }
758    
759     printf(GetString(STR_READING_ROM_FILE));
760    
761     // Get file size
762     off_t rom_size = 0;
763     file.GetSize(&rom_size);
764    
765     uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work
766     ssize_t actual = file.Read((void *)rom, ROM_SIZE);
767 gbeauche 1.2
768     // Decode Mac ROM
769     if (!DecodeROM(rom, actual)) {
770     if (rom_size != 4*1024*1024)
771 cebix 1.1 throw rom_size_error();
772     else
773     throw file_read_error();
774     }
775 gbeauche 1.2 delete[] rom;
776 cebix 1.1 }
777    
778    
779     /*
780     * Emulator thread function
781     */
782    
783     status_t SheepShaver::emul_func(void *arg)
784     {
785     SheepShaver *obj = (SheepShaver *)arg;
786    
787     // Install interrupt signal handler
788     sigemptyset(&obj->sigusr1_action.sa_mask);
789     obj->sigusr1_action.sa_handler = (__signal_func_ptr)(obj->sigusr1_invoc);
790     obj->sigusr1_action.sa_flags = 0;
791     obj->sigusr1_action.sa_userdata = arg;
792     sigaction(SIGUSR1, &obj->sigusr1_action, NULL);
793    
794     // Install data access signal handler
795     sigemptyset(&obj->sigsegv_action.sa_mask);
796     obj->sigsegv_action.sa_handler = (__signal_func_ptr)(obj->sigsegv_invoc);
797     obj->sigsegv_action.sa_flags = 0;
798     obj->sigsegv_action.sa_userdata = arg;
799     sigaction(SIGSEGV, &obj->sigsegv_action, NULL);
800    
801     #if !EMULATED_PPC
802     // Install illegal instruction signal handler
803     sigemptyset(&obj->sigill_action.sa_mask);
804     obj->sigill_action.sa_handler = (__signal_func_ptr)(obj->sigill_invoc);
805     obj->sigill_action.sa_flags = 0;
806     obj->sigill_action.sa_userdata = arg;
807     sigaction(SIGILL, &obj->sigill_action, NULL);
808     #endif
809    
810     // Exceptions will send signals
811     disable_debugger(true);
812    
813     // Install signal stack
814     sig_stack = malloc(SIG_STACK_SIZE);
815     extra_stack = malloc(SIG_STACK_SIZE);
816     set_signal_stack(sig_stack, SIG_STACK_SIZE);
817    
818     // We're now ready to receive signals
819     obj->ReadyForSignals = true;
820    
821     // Jump to ROM boot routine
822     D(bug("Jumping to ROM\n"));
823     obj->jump_to_rom(ROM_BASE + 0x310000);
824     D(bug("Returned from ROM\n"));
825    
826     // We're no longer ready to receive signals
827     obj->ReadyForSignals = false;
828     obj->AllowQuitting = true;
829    
830     // Quit program
831     be_app->PostMessage(B_QUIT_REQUESTED);
832     return 0;
833     }
834    
835    
836     /*
837     * Jump into Mac ROM, start 680x0 emulator
838     * (also contains other EMUL_RETURN and EMUL_OP routines)
839     */
840    
841     #if EMULATED_PPC
842     extern void emul_ppc(uint32 start);
843     extern void init_emul_ppc(void);
844     void SheepShaver::jump_to_rom(uint32 entry)
845     {
846     init_emul_ppc();
847     emul_ppc(entry);
848     }
849     #else
850     asm void SheepShaver::jump_to_rom(register uint32 entry)
851     {
852     // Create stack frame
853     mflr r0
854     stw r0,8(r1)
855     mfcr r0
856     stw r0,4(r1)
857     stwu r1,-(56+19*4+18*8)(r1)
858    
859     // Save PowerPC registers
860     stmw r13,56(r1)
861     stfd f14,56+19*4+0*8(r1)
862     stfd f15,56+19*4+1*8(r1)
863     stfd f16,56+19*4+2*8(r1)
864     stfd f17,56+19*4+3*8(r1)
865     stfd f18,56+19*4+4*8(r1)
866     stfd f19,56+19*4+5*8(r1)
867     stfd f20,56+19*4+6*8(r1)
868     stfd f21,56+19*4+7*8(r1)
869     stfd f22,56+19*4+8*8(r1)
870     stfd f23,56+19*4+9*8(r1)
871     stfd f24,56+19*4+10*8(r1)
872     stfd f25,56+19*4+11*8(r1)
873     stfd f26,56+19*4+12*8(r1)
874     stfd f27,56+19*4+13*8(r1)
875     stfd f28,56+19*4+14*8(r1)
876     stfd f29,56+19*4+15*8(r1)
877     stfd f30,56+19*4+16*8(r1)
878     stfd f31,56+19*4+17*8(r1)
879    
880     // Move entry address to ctr, get pointer to Emulator Data
881     mtctr r4
882     lwz r4,SheepShaver.emulator_data(r3)
883    
884     // Skip over EMUL_RETURN routine and get its address
885     bl @1
886    
887    
888     /*
889     * EMUL_RETURN: Returned from emulator
890     */
891    
892     // Restore PowerPC registers
893     lwz r1,XLM_EMUL_RETURN_STACK
894     lwz r2,XLM_TOC
895     lmw r13,56(r1)
896     lfd f14,56+19*4+0*8(r1)
897     lfd f15,56+19*4+1*8(r1)
898     lfd f16,56+19*4+2*8(r1)
899     lfd f17,56+19*4+3*8(r1)
900     lfd f18,56+19*4+4*8(r1)
901     lfd f19,56+19*4+5*8(r1)
902     lfd f20,56+19*4+6*8(r1)
903     lfd f21,56+19*4+7*8(r1)
904     lfd f22,56+19*4+8*8(r1)
905     lfd f23,56+19*4+9*8(r1)
906     lfd f24,56+19*4+10*8(r1)
907     lfd f25,56+19*4+11*8(r1)
908     lfd f26,56+19*4+12*8(r1)
909     lfd f27,56+19*4+13*8(r1)
910     lfd f28,56+19*4+14*8(r1)
911     lfd f29,56+19*4+15*8(r1)
912     lfd f30,56+19*4+16*8(r1)
913     lfd f31,56+19*4+17*8(r1)
914    
915     // Exiting from 68k emulator
916     li r0,1
917     stw r0,XLM_IRQ_NEST
918     li r0,MODE_NATIVE
919     stw r0,XLM_RUN_MODE
920    
921     // Return to caller of jump_to_rom()
922     lwz r0,56+19*4+18*8+8(r1)
923     mtlr r0
924     lwz r0,56+19*4+18*8+4(r1)
925     mtcrf 0xff,r0
926     addi r1,r1,56+19*4+18*8
927     blr
928    
929    
930     // Save address of EMUL_RETURN routine for 68k emulator patch
931     @1 mflr r0
932     stw r0,XLM_EMUL_RETURN_PROC
933    
934     // Skip over EXEC_RETURN routine and get its address
935     bl @2
936    
937    
938     /*
939     * EXEC_RETURN: Returned from 68k routine executed with Execute68k()
940     */
941    
942     // Save r25 (contains current 68k interrupt level)
943     stw r25,XLM_68K_R25
944    
945     // Reentering EMUL_OP mode
946     li r0,MODE_EMUL_OP
947     stw r0,XLM_RUN_MODE
948    
949     // Save 68k registers
950     lwz r4,56+19*4+18*8+12(r1)
951     stw r8,M68kRegisters.d[0](r4)
952     stw r9,M68kRegisters.d[1](r4)
953     stw r10,M68kRegisters.d[2](r4)
954     stw r11,M68kRegisters.d[3](r4)
955     stw r12,M68kRegisters.d[4](r4)
956     stw r13,M68kRegisters.d[5](r4)
957     stw r14,M68kRegisters.d[6](r4)
958     stw r15,M68kRegisters.d[7](r4)
959     stw r16,M68kRegisters.a[0](r4)
960     stw r17,M68kRegisters.a[1](r4)
961     stw r18,M68kRegisters.a[2](r4)
962     stw r19,M68kRegisters.a[3](r4)
963     stw r20,M68kRegisters.a[4](r4)
964     stw r21,M68kRegisters.a[5](r4)
965     stw r22,M68kRegisters.a[6](r4)
966    
967     // Restore PowerPC registers
968     lmw r13,56(r1)
969     #if SAVE_FP_EXEC_68K
970     lfd f14,56+19*4+0*8(r1)
971     lfd f15,56+19*4+1*8(r1)
972     lfd f16,56+19*4+2*8(r1)
973     lfd f17,56+19*4+3*8(r1)
974     lfd f18,56+19*4+4*8(r1)
975     lfd f19,56+19*4+5*8(r1)
976     lfd f20,56+19*4+6*8(r1)
977     lfd f21,56+19*4+7*8(r1)
978     lfd f22,56+19*4+8*8(r1)
979     lfd f23,56+19*4+9*8(r1)
980     lfd f24,56+19*4+10*8(r1)
981     lfd f25,56+19*4+11*8(r1)
982     lfd f26,56+19*4+12*8(r1)
983     lfd f27,56+19*4+13*8(r1)
984     lfd f28,56+19*4+14*8(r1)
985     lfd f29,56+19*4+15*8(r1)
986     lfd f30,56+19*4+16*8(r1)
987     lfd f31,56+19*4+17*8(r1)
988     #endif
989    
990     // Return to caller
991     lwz r0,56+19*4+18*8+8(r1)
992     mtlr r0
993     addi r1,r1,56+19*4+18*8
994     blr
995    
996    
997     // Stave address of EXEC_RETURN routine for 68k emulator patch
998     @2 mflr r0
999     stw r0,XLM_EXEC_RETURN_PROC
1000    
1001     // Skip over EMUL_BREAK/EMUL_OP routine and get its address
1002     bl @3
1003    
1004    
1005     /*
1006     * EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
1007     *
1008     * 68k registers are stored in a M68kRegisters struct on the stack
1009     * which the native routine may read and modify
1010     */
1011    
1012     // Save r25 (contains current 68k interrupt level)
1013     stw r25,XLM_68K_R25
1014    
1015     // Entering EMUL_OP mode within 68k emulator
1016     li r0,MODE_EMUL_OP
1017     stw r0,XLM_RUN_MODE
1018    
1019     // Create PowerPC stack frame, reserve space for M68kRegisters
1020     mr r3,r1
1021     subi r1,r1,56 // Fake "caller" frame
1022     rlwinm r1,r1,0,0,29 // Align stack
1023    
1024     mfcr r0
1025     rlwinm r0,r0,0,11,8
1026     stw r0,4(r1)
1027     mfxer r0
1028     stw r0,16(r1)
1029     stw r2,12(r1)
1030     stwu r1,-(56+16*4+15*8)(r1)
1031     lwz r2,XLM_TOC
1032    
1033     // Save 68k registers
1034     stw r8,56+M68kRegisters.d[0](r1)
1035     stw r9,56+M68kRegisters.d[1](r1)
1036     stw r10,56+M68kRegisters.d[2](r1)
1037     stw r11,56+M68kRegisters.d[3](r1)
1038     stw r12,56+M68kRegisters.d[4](r1)
1039     stw r13,56+M68kRegisters.d[5](r1)
1040     stw r14,56+M68kRegisters.d[6](r1)
1041     stw r15,56+M68kRegisters.d[7](r1)
1042     stw r16,56+M68kRegisters.a[0](r1)
1043     stw r17,56+M68kRegisters.a[1](r1)
1044     stw r18,56+M68kRegisters.a[2](r1)
1045     stw r19,56+M68kRegisters.a[3](r1)
1046     stw r20,56+M68kRegisters.a[4](r1)
1047     stw r21,56+M68kRegisters.a[5](r1)
1048     stw r22,56+M68kRegisters.a[6](r1)
1049     stw r3,56+M68kRegisters.a[7](r1)
1050     stfd f0,56+16*4+0*8(r1)
1051     stfd f1,56+16*4+1*8(r1)
1052     stfd f2,56+16*4+2*8(r1)
1053     stfd f3,56+16*4+3*8(r1)
1054     stfd f4,56+16*4+4*8(r1)
1055     stfd f5,56+16*4+5*8(r1)
1056     stfd f6,56+16*4+6*8(r1)
1057     stfd f7,56+16*4+7*8(r1)
1058     mffs f0
1059     stfd f8,56+16*4+8*8(r1)
1060     stfd f9,56+16*4+9*8(r1)
1061     stfd f10,56+16*4+10*8(r1)
1062     stfd f11,56+16*4+11*8(r1)
1063     stfd f12,56+16*4+12*8(r1)
1064     stfd f13,56+16*4+13*8(r1)
1065     stfd f0,56+16*4+14*8(r1)
1066    
1067     // Execute native routine
1068     addi r3,r1,56
1069     mr r4,r24
1070     bl EmulOp
1071    
1072     // Restore 68k registers
1073     lwz r8,56+M68kRegisters.d[0](r1)
1074     lwz r9,56+M68kRegisters.d[1](r1)
1075     lwz r10,56+M68kRegisters.d[2](r1)
1076     lwz r11,56+M68kRegisters.d[3](r1)
1077     lwz r12,56+M68kRegisters.d[4](r1)
1078     lwz r13,56+M68kRegisters.d[5](r1)
1079     lwz r14,56+M68kRegisters.d[6](r1)
1080     lwz r15,56+M68kRegisters.d[7](r1)
1081     lwz r16,56+M68kRegisters.a[0](r1)
1082     lwz r17,56+M68kRegisters.a[1](r1)
1083     lwz r18,56+M68kRegisters.a[2](r1)
1084     lwz r19,56+M68kRegisters.a[3](r1)
1085     lwz r20,56+M68kRegisters.a[4](r1)
1086     lwz r21,56+M68kRegisters.a[5](r1)
1087     lwz r22,56+M68kRegisters.a[6](r1)
1088     lwz r3,56+M68kRegisters.a[7](r1)
1089     lfd f13,56+16*4+14*8(r1)
1090     lfd f0,56+16*4+0*8(r1)
1091     lfd f1,56+16*4+1*8(r1)
1092     lfd f2,56+16*4+2*8(r1)
1093     lfd f3,56+16*4+3*8(r1)
1094     lfd f4,56+16*4+4*8(r1)
1095     lfd f5,56+16*4+5*8(r1)
1096     lfd f6,56+16*4+6*8(r1)
1097     lfd f7,56+16*4+7*8(r1)
1098     mtfsf 0xff,f13
1099     lfd f8,56+16*4+8*8(r1)
1100     lfd f9,56+16*4+9*8(r1)
1101     lfd f10,56+16*4+10*8(r1)
1102     lfd f11,56+16*4+11*8(r1)
1103     lfd f12,56+16*4+12*8(r1)
1104     lfd f13,56+16*4+13*8(r1)
1105    
1106     // Delete PowerPC stack frame
1107     lwz r2,56+16*4+15*8+12(r1)
1108     lwz r0,56+16*4+15*8+16(r1)
1109     mtxer r0
1110     lwz r0,56+16*4+15*8+4(r1)
1111     mtcrf 0xff,r0
1112     mr r1,r3
1113    
1114     // Reeintering 68k emulator
1115     li r0,MODE_68K
1116     stw r0,XLM_RUN_MODE
1117    
1118     // Set r0 to 0 for 68k emulator
1119     li r0,0
1120    
1121     // Execute next 68k opcode
1122     rlwimi r29,r27,3,13,28
1123     lhau r27,2(r24)
1124     mtlr r29
1125     blr
1126    
1127    
1128     // Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch
1129     @3 mflr r0
1130     stw r0,XLM_EMUL_OP_PROC
1131    
1132     // Save stack pointer for EMUL_RETURN
1133     stw r1,XLM_EMUL_RETURN_STACK
1134    
1135     // Preset registers for ROM boot routine
1136     lis r3,0x40b0 // Pointer to ROM boot structure
1137     ori r3,r3,0xd000
1138    
1139     // 68k emulator is now active
1140     li r0,MODE_68K
1141     stw r0,XLM_RUN_MODE
1142    
1143     // Jump to ROM
1144     bctr
1145     }
1146     #endif
1147    
1148    
1149     #if !EMULATED_PPC
1150     /*
1151     * Execute 68k subroutine (must be ended with RTS)
1152     * This must only be called by the emul_thread when in EMUL_OP mode
1153     * r->a[7] is unused, the routine runs on the caller's stack
1154     */
1155    
1156     #if SAFE_EXEC_68K
1157     void execute_68k(uint32 pc, M68kRegisters *r);
1158    
1159     void Execute68k(uint32 pc, M68kRegisters *r)
1160     {
1161     if (*(uint32 *)XLM_RUN_MODE != MODE_EMUL_OP)
1162     printf("FATAL: Execute68k() not called from EMUL_OP mode\n");
1163     if (find_thread(NULL) != the_app->emul_thread)
1164     printf("FATAL: Execute68k() not called from emul_thread\n");
1165     execute_68k(pc, r);
1166     }
1167    
1168     asm void execute_68k(register uint32 pc, register M68kRegisters *r)
1169     #else
1170     asm void Execute68k(register uint32 pc, register M68kRegisters *r)
1171     #endif
1172     {
1173     // Create stack frame
1174     mflr r0
1175     stw r0,8(r1)
1176     stw r4,12(r1)
1177     stwu r1,-(56+19*4+18*8)(r1)
1178    
1179     // Save PowerPC registers
1180     stmw r13,56(r1)
1181     #if SAVE_FP_EXEC_68K
1182     stfd f14,56+19*4+0*8(r1)
1183     stfd f15,56+19*4+1*8(r1)
1184     stfd f16,56+19*4+2*8(r1)
1185     stfd f17,56+19*4+3*8(r1)
1186     stfd f18,56+19*4+4*8(r1)
1187     stfd f19,56+19*4+5*8(r1)
1188     stfd f20,56+19*4+6*8(r1)
1189     stfd f21,56+19*4+7*8(r1)
1190     stfd f22,56+19*4+8*8(r1)
1191     stfd f23,56+19*4+9*8(r1)
1192     stfd f24,56+19*4+10*8(r1)
1193     stfd f25,56+19*4+11*8(r1)
1194     stfd f26,56+19*4+12*8(r1)
1195     stfd f27,56+19*4+13*8(r1)
1196     stfd f28,56+19*4+14*8(r1)
1197     stfd f29,56+19*4+15*8(r1)
1198     stfd f30,56+19*4+16*8(r1)
1199     stfd f31,56+19*4+17*8(r1)
1200     #endif
1201    
1202     // Set up registers for 68k emulator
1203     lwz r31,XLM_KERNEL_DATA // Pointer to Kernel Data
1204     addi r31,r31,0x1000
1205     li r0,0
1206     mtcrf 0xff,r0
1207     creqv 11,11,11 // Supervisor mode
1208     lwz r8,M68kRegisters.d[0](r4)
1209     lwz r9,M68kRegisters.d[1](r4)
1210     lwz r10,M68kRegisters.d[2](r4)
1211     lwz r11,M68kRegisters.d[3](r4)
1212     lwz r12,M68kRegisters.d[4](r4)
1213     lwz r13,M68kRegisters.d[5](r4)
1214     lwz r14,M68kRegisters.d[6](r4)
1215     lwz r15,M68kRegisters.d[7](r4)
1216     lwz r16,M68kRegisters.a[0](r4)
1217     lwz r17,M68kRegisters.a[1](r4)
1218     lwz r18,M68kRegisters.a[2](r4)
1219     lwz r19,M68kRegisters.a[3](r4)
1220     lwz r20,M68kRegisters.a[4](r4)
1221     lwz r21,M68kRegisters.a[5](r4)
1222     lwz r22,M68kRegisters.a[6](r4)
1223     li r23,0
1224     mr r24,r3
1225     lwz r25,XLM_68K_R25 // MSB of SR
1226     li r26,0
1227     li r28,0 // VBR
1228     lwz r29,0x74(r31) // Pointer to opcode table
1229     lwz r30,0x78(r31) // Address of emulator
1230    
1231     // Push return address (points to EXEC_RETURN opcode) on stack
1232     li r0,XLM_EXEC_RETURN_OPCODE
1233     stwu r0,-4(r1)
1234    
1235     // Reentering 68k emulator
1236     li r0,MODE_68K
1237     stw r0,XLM_RUN_MODE
1238    
1239     // Set r0 to 0 for 68k emulator
1240     li r0,0
1241    
1242     // Execute 68k opcode
1243     lha r27,0(r24)
1244     rlwimi r29,r27,3,13,28
1245     lhau r27,2(r24)
1246     mtlr r29
1247     blr
1248     }
1249    
1250    
1251     /*
1252     * Execute 68k A-Trap from EMUL_OP routine
1253     * r->a[7] is unused, the routine runs on the caller's stack
1254     */
1255    
1256     void Execute68kTrap(uint16 trap, M68kRegisters *r)
1257     {
1258     uint16 proc[2] = {trap, M68K_RTS};
1259     Execute68k((uint32)proc, r);
1260     }
1261    
1262    
1263     /*
1264     * Execute PPC code from EMUL_OP routine (real mode switch)
1265     */
1266    
1267     void ExecutePPC(void (*func)())
1268     {
1269     RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, func);
1270     M68kRegisters r;
1271     Execute68k((uint32)&desc, &r);
1272     }
1273    
1274    
1275     /*
1276     * Quit emulator (must only be called from main thread)
1277     */
1278    
1279     asm void QuitEmulator(void)
1280     {
1281     lwz r0,XLM_EMUL_RETURN_PROC
1282     mtlr r0
1283     blr
1284     }
1285     #endif
1286    
1287    
1288     /*
1289     * Dump 68k registers
1290     */
1291    
1292     void Dump68kRegs(M68kRegisters *r)
1293     {
1294     // Display 68k registers
1295     for (int i=0; i<8; i++) {
1296     printf("d%d: %08lx", i, r->d[i]);
1297     if (i == 3 || i == 7)
1298     printf("\n");
1299     else
1300     printf(", ");
1301     }
1302     for (int i=0; i<8; i++) {
1303     printf("a%d: %08lx", i, r->a[i]);
1304     if (i == 3 || i == 7)
1305     printf("\n");
1306     else
1307     printf(", ");
1308     }
1309     }
1310    
1311    
1312     /*
1313     * Make code executable
1314     */
1315    
1316     void MakeExecutable(int dummy, void *start, uint32 length)
1317     {
1318     if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE)))
1319     return;
1320     clear_caches(start, length, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE);
1321     }
1322    
1323    
1324     /*
1325     * Patch things after system startup (gets called by disk driver accRun routine)
1326     */
1327    
1328     void PatchAfterStartup(void)
1329     {
1330     ExecutePPC(VideoInstallAccel);
1331     InstallExtFS();
1332     }
1333    
1334    
1335     /*
1336     * NVRAM watchdog thread (saves NVRAM every minute)
1337     */
1338    
1339     static status_t SheepShaver::nvram_func(void *arg)
1340     {
1341     SheepShaver *obj = (SheepShaver *)arg;
1342    
1343     while (obj->NVRAMThreadActive) {
1344     snooze(60*1000000);
1345     if (memcmp(obj->last_xpram, XPRAM, XPRAM_SIZE)) {
1346     memcpy(obj->last_xpram, XPRAM, XPRAM_SIZE);
1347     SaveXPRAM();
1348     }
1349     }
1350     return 0;
1351     }
1352    
1353    
1354     /*
1355     * 60Hz thread (really 60.15Hz)
1356     */
1357    
1358     status_t SheepShaver::tick_func(void *arg)
1359     {
1360     SheepShaver *obj = (SheepShaver *)arg;
1361     int tick_counter = 0;
1362     bigtime_t current = system_time();
1363    
1364     while (obj->TickThreadActive) {
1365    
1366     // Wait
1367     current += 16625;
1368     snooze_until(current, B_SYSTEM_TIMEBASE);
1369    
1370     // Pseudo Mac 1Hz interrupt, update local time
1371     if (++tick_counter > 60) {
1372     tick_counter = 0;
1373     WriteMacInt32(0x20c, TimerDateTime());
1374     }
1375    
1376     // 60Hz interrupt
1377     if (ReadMacInt32(XLM_IRQ_NEST) == 0) {
1378     SetInterruptFlag(INTFLAG_VIA);
1379     TriggerInterrupt();
1380     }
1381     }
1382     return 0;
1383     }
1384    
1385    
1386     /*
1387     * Trigger signal USR1 from another thread
1388     */
1389    
1390     void TriggerInterrupt(void)
1391     {
1392     #if 0
1393     WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1394     #else
1395     if (the_app->emul_thread > 0 && the_app->ReadyForSignals)
1396     send_signal(the_app->emul_thread, SIGUSR1);
1397     #endif
1398     }
1399    
1400    
1401     /*
1402     * Mutexes
1403     */
1404    
1405     struct B2_mutex {
1406     int dummy; //!!
1407     };
1408    
1409     B2_mutex *B2_create_mutex(void)
1410     {
1411     return new B2_mutex;
1412     }
1413    
1414     void B2_lock_mutex(B2_mutex *mutex)
1415     {
1416     }
1417    
1418     void B2_unlock_mutex(B2_mutex *mutex)
1419     {
1420     }
1421    
1422     void B2_delete_mutex(B2_mutex *mutex)
1423     {
1424     delete mutex;
1425     }
1426    
1427    
1428     /*
1429     * Set/clear interrupt flags (must be done atomically!)
1430     */
1431    
1432     volatile uint32 InterruptFlags = 0;
1433    
1434     void SetInterruptFlag(uint32 flag)
1435     {
1436     atomic_or((int32 *)&InterruptFlags, flag);
1437     }
1438    
1439     void ClearInterruptFlag(uint32 flag)
1440     {
1441     atomic_and((int32 *)&InterruptFlags, ~flag);
1442     }
1443    
1444    
1445     /*
1446     * Disable interrupts
1447     */
1448    
1449     void DisableInterrupt(void)
1450     {
1451     atomic_add((int32 *)XLM_IRQ_NEST, 1);
1452     }
1453    
1454    
1455     /*
1456     * Enable interrupts
1457     */
1458    
1459     void EnableInterrupt(void)
1460     {
1461     atomic_add((int32 *)XLM_IRQ_NEST, -1);
1462     }
1463    
1464    
1465     /*
1466     * USR1 handler
1467     */
1468    
1469     void SheepShaver::sigusr1_invoc(int sig, void *arg, vregs *r)
1470     {
1471     ((SheepShaver *)arg)->sigusr1_handler(r);
1472     }
1473    
1474     #if !EMULATED_PPC
1475     static asm void ppc_interrupt(register uint32 entry)
1476     {
1477     fralloc
1478    
1479     // Get address of return routine
1480     bl @1
1481    
1482     // Return routine
1483     frfree
1484     blr
1485    
1486     @1
1487     // Prepare registers for nanokernel interrupt routine
1488     mtctr r1
1489     lwz r1,XLM_KERNEL_DATA
1490     stw r6,0x018(r1)
1491     mfctr r6
1492     stw r6,0x004(r1)
1493     lwz r6,0x65c(r1)
1494     stw r7,0x13c(r6)
1495     stw r8,0x144(r6)
1496     stw r9,0x14c(r6)
1497     stw r10,0x154(r6)
1498     stw r11,0x15c(r6)
1499     stw r12,0x164(r6)
1500     stw r13,0x16c(r6)
1501    
1502     mflr r10
1503     mfcr r13
1504     lwz r7,0x660(r1)
1505     mflr r12
1506     rlwimi. r7,r7,8,0,0
1507     li r11,0
1508     ori r11,r11,0xf072 // MSR (SRR1)
1509     mtcrf 0x70,r11
1510     li r8,0
1511    
1512     // Enter nanokernel
1513     mtlr r3
1514     blr
1515     }
1516     #endif
1517    
1518     void SheepShaver::sigusr1_handler(vregs *r)
1519     {
1520     // Do nothing if interrupts are disabled
1521     if ((*(int32 *)XLM_IRQ_NEST) > 0)
1522     return;
1523    
1524     // Interrupt action depends on current run mode
1525     switch (*(uint32 *)XLM_RUN_MODE) {
1526     case MODE_68K:
1527     // 68k emulator active, trigger 68k interrupt level 1
1528     *(uint16 *)(kernel_data->v[0x67c >> 2]) = 1;
1529     r->cr |= kernel_data->v[0x674 >> 2];
1530     break;
1531    
1532     #if INTERRUPTS_IN_NATIVE_MODE
1533     case MODE_NATIVE:
1534     // 68k emulator inactive, in nanokernel?
1535     if (r->r1 != KernelDataAddr) {
1536     // No, prepare for 68k interrupt level 1
1537     *(uint16 *)(kernel_data->v[0x67c >> 2]) = 1;
1538     *(uint32 *)(kernel_data->v[0x658 >> 2] + 0xdc) |= kernel_data->v[0x674 >> 2];
1539    
1540     // Execute nanokernel interrupt routine (this will activate the 68k emulator)
1541     atomic_add((int32 *)XLM_IRQ_NEST, 1);
1542     if (ROMType == ROMTYPE_NEWWORLD)
1543     ppc_interrupt(ROM_BASE + 0x312b1c);
1544     else
1545     ppc_interrupt(ROM_BASE + 0x312a3c);
1546     }
1547     break;
1548     #endif
1549    
1550     #if INTERRUPTS_IN_EMUL_OP_MODE
1551     case MODE_EMUL_OP:
1552     // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0
1553     if ((*(uint32 *)XLM_68K_R25 & 7) == 0) {
1554    
1555     // Set extra stack for SIGSEGV handler
1556     set_signal_stack(extra_stack, SIG_STACK_SIZE);
1557     #if 1
1558     // Execute full 68k interrupt routine
1559     M68kRegisters r;
1560     uint32 old_r25 = *(uint32 *)XLM_68K_R25; // Save interrupt level
1561     *(uint32 *)XLM_68K_R25 = 0x21; // Execute with interrupt level 1
1562     static const uint16 proc[] = {
1563     0x3f3c, 0x0000, // move.w #$0000,-(sp) (fake format word)
1564     0x487a, 0x000a, // pea @1(pc) (return address)
1565     0x40e7, // move sr,-(sp) (saved SR)
1566     0x2078, 0x0064, // move.l $64,a0
1567     0x4ed0, // jmp (a0)
1568     M68K_RTS // @1
1569     };
1570     Execute68k((uint32)proc, &r);
1571     *(uint32 *)XLM_68K_R25 = old_r25; // Restore interrupt level
1572     #else
1573     // Only update cursor
1574     if (HasMacStarted()) {
1575     if (InterruptFlags & INTFLAG_VIA) {
1576     ClearInterruptFlag(INTFLAG_VIA);
1577     ADBInterrupt();
1578     ExecutePPC(VideoVBL);
1579     }
1580     }
1581     #endif
1582     // Reset normal signal stack
1583     set_signal_stack(sig_stack, SIG_STACK_SIZE);
1584     }
1585     break;
1586     #endif
1587     }
1588     }
1589    
1590    
1591     /*
1592     * SIGSEGV handler
1593     */
1594    
1595     static uint32 segv_r[32];
1596    
1597     #if !EMULATED_PPC
1598     asm void SheepShaver::sigsegv_invoc(register int sig, register void *arg, register vregs *r)
1599     {
1600     mflr r0
1601     stw r0,8(r1)
1602     stwu r1,-56(r1)
1603    
1604     lwz r3,segv_r(r2)
1605     stmw r13,13*4(r3)
1606    
1607     mr r3,r5
1608     bl sigsegv_handler
1609    
1610     lwz r3,segv_r(r2)
1611     lmw r13,13*4(r3)
1612    
1613     lwz r0,56+8(r1)
1614     mtlr r0
1615     addi r1,r1,56
1616     blr
1617     }
1618     #endif
1619    
1620     static void sigsegv_handler(vregs *r)
1621     {
1622     char str[256];
1623    
1624     // Fetch volatile registers
1625     segv_r[0] = r->r0;
1626     segv_r[1] = r->r1;
1627     segv_r[2] = r->r2;
1628     segv_r[3] = r->r3;
1629     segv_r[4] = r->r4;
1630     segv_r[5] = r->r5;
1631     segv_r[6] = r->r6;
1632     segv_r[7] = r->r7;
1633     segv_r[8] = r->r8;
1634     segv_r[9] = r->r9;
1635     segv_r[10] = r->r10;
1636     segv_r[11] = r->r11;
1637     segv_r[12] = r->r12;
1638    
1639     // Get opcode and divide into fields
1640     uint32 opcode = *(uint32 *)r->pc;
1641     uint32 primop = opcode >> 26;
1642     uint32 exop = (opcode >> 1) & 0x3ff;
1643     uint32 ra = (opcode >> 16) & 0x1f;
1644     uint32 rb = (opcode >> 11) & 0x1f;
1645     uint32 rd = (opcode >> 21) & 0x1f;
1646     uint32 imm = opcode & 0xffff;
1647    
1648     // Fault in Mac ROM or RAM?
1649     bool mac_fault = (r->pc >= ROM_BASE) && (r->pc < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc >= RAMBase) && (r->pc < (RAMBase + RAMSize));
1650     if (mac_fault) {
1651    
1652     // "VM settings" during MacOS 8 installation
1653     if (r->pc == ROM_BASE + 0x488160 && segv_r[20] == 0xf8000000) {
1654     r->pc += 4;
1655     segv_r[8] = 0;
1656     goto rti;
1657    
1658     // MacOS 8.5 installation
1659     } else if (r->pc == ROM_BASE + 0x488140 && segv_r[16] == 0xf8000000) {
1660     r->pc += 4;
1661     segv_r[8] = 0;
1662     goto rti;
1663    
1664     // MacOS 8 serial drivers on startup
1665     } else if (r->pc == ROM_BASE + 0x48e080 && (segv_r[8] == 0xf3012002 || segv_r[8] == 0xf3012000)) {
1666     r->pc += 4;
1667     segv_r[8] = 0;
1668     goto rti;
1669    
1670     // MacOS 8.1 serial drivers on startup
1671     } else if (r->pc == ROM_BASE + 0x48c5e0 && (segv_r[20] == 0xf3012002 || segv_r[20] == 0xf3012000)) {
1672     r->pc += 4;
1673     goto rti;
1674     } else if (r->pc == ROM_BASE + 0x4a10a0 && (segv_r[20] == 0xf3012002 || segv_r[20] == 0xf3012000)) {
1675     r->pc += 4;
1676     goto rti;
1677     }
1678     }
1679    
1680     // Analyze opcode
1681     enum {
1682     TYPE_UNKNOWN,
1683     TYPE_LOAD,
1684     TYPE_STORE
1685     } transfer_type = TYPE_UNKNOWN;
1686     enum {
1687     SIZE_UNKNOWN,
1688     SIZE_BYTE,
1689     SIZE_HALFWORD,
1690     SIZE_WORD
1691     } transfer_size = SIZE_UNKNOWN;
1692     enum {
1693     MODE_UNKNOWN,
1694     MODE_NORM,
1695     MODE_U,
1696     MODE_X,
1697     MODE_UX
1698     } addr_mode = MODE_UNKNOWN;
1699     switch (primop) {
1700     case 31:
1701     switch (exop) {
1702     case 23: // lwzx
1703     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
1704     case 55: // lwzux
1705     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
1706     case 87: // lbzx
1707     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
1708     case 119: // lbzux
1709     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
1710     case 151: // stwx
1711     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_X; break;
1712     case 183: // stwux
1713     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_UX; break;
1714     case 215: // stbx
1715     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_X; break;
1716     case 247: // stbux
1717     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_UX; break;
1718     case 279: // lhzx
1719     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1720     case 311: // lhzux
1721     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1722     case 343: // lhax
1723     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1724     case 375: // lhaux
1725     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1726     case 407: // sthx
1727     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_X; break;
1728     case 439: // sthux
1729     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_UX; break;
1730     }
1731     break;
1732    
1733     case 32: // lwz
1734     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
1735     case 33: // lwzu
1736     transfer_type = TYPE_LOAD; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
1737     case 34: // lbz
1738     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
1739     case 35: // lbzu
1740     transfer_type = TYPE_LOAD; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
1741     case 36: // stw
1742     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_NORM; break;
1743     case 37: // stwu
1744     transfer_type = TYPE_STORE; transfer_size = SIZE_WORD; addr_mode = MODE_U; break;
1745     case 38: // stb
1746     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_NORM; break;
1747     case 39: // stbu
1748     transfer_type = TYPE_STORE; transfer_size = SIZE_BYTE; addr_mode = MODE_U; break;
1749     case 40: // lhz
1750     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1751     case 41: // lhzu
1752     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1753     case 42: // lha
1754     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1755     case 43: // lhau
1756     transfer_type = TYPE_LOAD; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1757     case 44: // sth
1758     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_NORM; break;
1759     case 45: // sthu
1760     transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1761     }
1762    
1763     // Calculate effective address
1764     uint32 addr = 0;
1765     switch (addr_mode) {
1766     case MODE_X:
1767     case MODE_UX:
1768     if (ra == 0)
1769     addr = segv_r[rb];
1770     else
1771     addr = segv_r[ra] + segv_r[rb];
1772     break;
1773     case MODE_NORM:
1774     case MODE_U:
1775     if (ra == 0)
1776     addr = (int32)(int16)imm;
1777     else
1778     addr = segv_r[ra] + (int32)(int16)imm;
1779     break;
1780     default:
1781     break;
1782     }
1783    
1784     // Ignore ROM writes
1785     if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
1786     D(bug("WARNING: %s write access to ROM at %p, pc %p\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->pc));
1787     if (addr_mode == MODE_U || addr_mode == MODE_UX)
1788     segv_r[ra] = addr;
1789     r->pc += 4;
1790     goto rti;
1791     }
1792    
1793     // Fault in Mac ROM or RAM?
1794     if (mac_fault) {
1795    
1796     // Ignore illegal memory accesses?
1797     if (PrefsFindBool("ignoresegv")) {
1798     if (addr_mode == MODE_U || addr_mode == MODE_UX)
1799     segv_r[ra] = addr;
1800     if (transfer_type == TYPE_LOAD)
1801     segv_r[rd] = 0;
1802     r->pc += 4;
1803     goto rti;
1804     }
1805    
1806     // In GUI mode, show error alert
1807     if (!PrefsFindBool("nogui")) {
1808     if (transfer_type == TYPE_LOAD || transfer_type == TYPE_STORE)
1809     sprintf(str, GetString(STR_MEM_ACCESS_ERR), transfer_size == SIZE_BYTE ? "byte" : transfer_size == SIZE_HALFWORD ? "halfword" : "word", transfer_type == TYPE_LOAD ? GetString(STR_MEM_ACCESS_READ) : GetString(STR_MEM_ACCESS_WRITE), addr, r->pc, segv_r[24], segv_r[1]);
1810     else
1811     sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc, segv_r[24], segv_r[1], opcode);
1812     ErrorAlert(str);
1813     QuitEmulator();
1814     return;
1815     }
1816     }
1817    
1818     // For all other errors, jump into debugger
1819     sprintf(str, "SIGSEGV\n"
1820     " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
1821     " xer %08lx cr %08lx fpscr %08lx\n"
1822     " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
1823     " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
1824     " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
1825     " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
1826     " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
1827     " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
1828     " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
1829     " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
1830     r->pc, r->lr, r->ctr, r->msr,
1831     r->xer, r->cr, r->fpscr,
1832     r->r0, r->r1, r->r2, r->r3,
1833     r->r4, r->r5, r->r6, r->r7,
1834     r->r8, r->r9, r->r10, r->r11,
1835     r->r12, segv_r[13], segv_r[14], segv_r[15],
1836     segv_r[16], segv_r[17], segv_r[18], segv_r[19],
1837     segv_r[20], segv_r[21], segv_r[22], segv_r[23],
1838     segv_r[24], segv_r[25], segv_r[26], segv_r[27],
1839     segv_r[28], segv_r[29], segv_r[30], segv_r[31]);
1840     VideoQuitFullScreen();
1841     disable_debugger(false);
1842     debugger(str);
1843     exit(1);
1844     return;
1845    
1846     rti:
1847     // Restore volatile registers
1848     r->r0 = segv_r[0];
1849     r->r1 = segv_r[1];
1850     r->r2 = segv_r[2];
1851     r->r3 = segv_r[3];
1852     r->r4 = segv_r[4];
1853     r->r5 = segv_r[5];
1854     r->r6 = segv_r[6];
1855     r->r7 = segv_r[7];
1856     r->r8 = segv_r[8];
1857     r->r9 = segv_r[9];
1858     r->r10 = segv_r[10];
1859     r->r11 = segv_r[11];
1860     r->r12 = segv_r[12];
1861     }
1862    
1863    
1864     /*
1865     * SIGILL handler
1866     */
1867    
1868     #if !EMULATED_PPC
1869     asm void SheepShaver::sigill_invoc(register int sig, register void *arg, register vregs *r)
1870     {
1871     mflr r0
1872     stw r0,8(r1)
1873     stwu r1,-56(r1)
1874    
1875     lwz r3,segv_r(r2)
1876     stmw r13,13*4(r3)
1877    
1878     mr r3,r5
1879     bl sigill_handler
1880    
1881     lwz r3,segv_r(r2)
1882     lmw r13,13*4(r3)
1883    
1884     lwz r0,56+8(r1)
1885     mtlr r0
1886     addi r1,r1,56
1887     blr
1888     }
1889     #endif
1890    
1891     static void sigill_handler(vregs *r)
1892     {
1893     char str[256];
1894    
1895     // Fetch volatile registers
1896     segv_r[0] = r->r0;
1897     segv_r[1] = r->r1;
1898     segv_r[2] = r->r2;
1899     segv_r[3] = r->r3;
1900     segv_r[4] = r->r4;
1901     segv_r[5] = r->r5;
1902     segv_r[6] = r->r6;
1903     segv_r[7] = r->r7;
1904     segv_r[8] = r->r8;
1905     segv_r[9] = r->r9;
1906     segv_r[10] = r->r10;
1907     segv_r[11] = r->r11;
1908     segv_r[12] = r->r12;
1909    
1910     // Get opcode and divide into fields
1911     uint32 opcode = *(uint32 *)r->pc;
1912     uint32 primop = opcode >> 26;
1913     uint32 exop = (opcode >> 1) & 0x3ff;
1914     uint32 ra = (opcode >> 16) & 0x1f;
1915     uint32 rb = (opcode >> 11) & 0x1f;
1916     uint32 rd = (opcode >> 21) & 0x1f;
1917     uint32 imm = opcode & 0xffff;
1918    
1919     // Fault in Mac ROM or RAM?
1920     bool mac_fault = (r->pc >= ROM_BASE) && (r->pc < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc >= RAMBase) && (r->pc < (RAMBase + RAMSize));
1921     if (mac_fault) {
1922    
1923     switch (primop) {
1924     case 9: // POWER instructions
1925     case 22:
1926     power_inst: sprintf(str, GetString(STR_POWER_INSTRUCTION_ERR), r->pc, segv_r[1], opcode);
1927     ErrorAlert(str);
1928     QuitEmulator();
1929     return;
1930    
1931     case 31:
1932     switch (exop) {
1933     case 83: // mfmsr
1934     segv_r[rd] = 0xf072;
1935     r->pc += 4;
1936     goto rti;
1937    
1938     case 210: // mtsr
1939     case 242: // mtsrin
1940     case 306: // tlbie
1941     r->pc += 4;
1942     goto rti;
1943    
1944     case 339: { // mfspr
1945     int spr = ra | (rb << 5);
1946     switch (spr) {
1947     case 0: // MQ
1948     case 22: // DEC
1949     case 952: // MMCR0
1950     case 953: // PMC1
1951     case 954: // PMC2
1952     case 955: // SIA
1953     case 956: // MMCR1
1954     case 957: // PMC3
1955     case 958: // PMC4
1956     case 959: // SDA
1957     r->pc += 4;
1958     goto rti;
1959     case 25: // SDR1
1960     segv_r[rd] = 0xdead001f;
1961     r->pc += 4;
1962     goto rti;
1963     case 287: // PVR
1964     segv_r[rd] = PVR;
1965     r->pc += 4;
1966     goto rti;
1967     }
1968     break;
1969     }
1970    
1971     case 467: { // mtspr
1972     int spr = ra | (rb << 5);
1973     switch (spr) {
1974     case 0: // MQ
1975     case 22: // DEC
1976     case 275: // SPRG3
1977     case 528: // IBAT0U
1978     case 529: // IBAT0L
1979     case 530: // IBAT1U
1980     case 531: // IBAT1L
1981     case 532: // IBAT2U
1982     case 533: // IBAT2L
1983     case 534: // IBAT3U
1984     case 535: // IBAT3L
1985     case 536: // DBAT0U
1986     case 537: // DBAT0L
1987     case 538: // DBAT1U
1988     case 539: // DBAT1L
1989     case 540: // DBAT2U
1990     case 541: // DBAT2L
1991     case 542: // DBAT3U
1992     case 543: // DBAT3L
1993     case 952: // MMCR0
1994     case 953: // PMC1
1995     case 954: // PMC2
1996     case 955: // SIA
1997     case 956: // MMCR1
1998     case 957: // PMC3
1999     case 958: // PMC4
2000     case 959: // SDA
2001     r->pc += 4;
2002     goto rti;
2003     }
2004     break;
2005     }
2006    
2007     case 29: case 107: case 152: case 153: // POWER instructions
2008     case 184: case 216: case 217: case 248:
2009     case 264: case 277: case 331: case 360:
2010     case 363: case 488: case 531: case 537:
2011     case 541: case 664: case 665: case 696:
2012     case 728: case 729: case 760: case 920:
2013     case 921: case 952:
2014     goto power_inst;
2015     }
2016     }
2017    
2018     // In GUI mode, show error alert
2019     if (!PrefsFindBool("nogui")) {
2020     sprintf(str, GetString(STR_UNKNOWN_SEGV_ERR), r->pc, segv_r[24], segv_r[1], opcode);
2021     ErrorAlert(str);
2022     QuitEmulator();
2023     return;
2024     }
2025     }
2026    
2027     // For all other errors, jump into debugger
2028     sprintf(str, "SIGILL\n"
2029     " pc %08lx lr %08lx ctr %08lx msr %08lx\n"
2030     " xer %08lx cr %08lx fpscr %08lx\n"
2031     " r0 %08lx r1 %08lx r2 %08lx r3 %08lx\n"
2032     " r4 %08lx r5 %08lx r6 %08lx r7 %08lx\n"
2033     " r8 %08lx r9 %08lx r10 %08lx r11 %08lx\n"
2034     " r12 %08lx r13 %08lx r14 %08lx r15 %08lx\n"
2035     " r16 %08lx r17 %08lx r18 %08lx r19 %08lx\n"
2036     " r20 %08lx r21 %08lx r22 %08lx r23 %08lx\n"
2037     " r24 %08lx r25 %08lx r26 %08lx r27 %08lx\n"
2038     " r28 %08lx r29 %08lx r30 %08lx r31 %08lx\n",
2039     r->pc, r->lr, r->ctr, r->msr,
2040     r->xer, r->cr, r->fpscr,
2041     r->r0, r->r1, r->r2, r->r3,
2042     r->r4, r->r5, r->r6, r->r7,
2043     r->r8, r->r9, r->r10, r->r11,
2044     r->r12, segv_r[13], segv_r[14], segv_r[15],
2045     segv_r[16], segv_r[17], segv_r[18], segv_r[19],
2046     segv_r[20], segv_r[21], segv_r[22], segv_r[23],
2047     segv_r[24], segv_r[25], segv_r[26], segv_r[27],
2048     segv_r[28], segv_r[29], segv_r[30], segv_r[31]);
2049     VideoQuitFullScreen();
2050     disable_debugger(false);
2051     debugger(str);
2052     exit(1);
2053     return;
2054    
2055     rti:
2056     // Restore volatile registers
2057     r->r0 = segv_r[0];
2058     r->r1 = segv_r[1];
2059     r->r2 = segv_r[2];
2060     r->r3 = segv_r[3];
2061     r->r4 = segv_r[4];
2062     r->r5 = segv_r[5];
2063     r->r6 = segv_r[6];
2064     r->r7 = segv_r[7];
2065     r->r8 = segv_r[8];
2066     r->r9 = segv_r[9];
2067     r->r10 = segv_r[10];
2068     r->r11 = segv_r[11];
2069     r->r12 = segv_r[12];
2070     }
2071    
2072    
2073     /*
2074     * Display error alert
2075     */
2076    
2077     void ErrorAlert(const char *text)
2078     {
2079     if (PrefsFindBool("nogui")) {
2080     printf(GetString(STR_SHELL_ERROR_PREFIX), text);
2081     return;
2082     }
2083     char str[256];
2084     sprintf(str, GetString(STR_GUI_ERROR_PREFIX), text);
2085     VideoQuitFullScreen();
2086     BAlert *alert = new BAlert(GetString(STR_ERROR_ALERT_TITLE), str, GetString(STR_QUIT_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
2087     alert->Go();
2088     }
2089    
2090    
2091     /*
2092     * Display warning alert
2093     */
2094    
2095     void WarningAlert(const char *text)
2096     {
2097     if (PrefsFindBool("nogui")) {
2098     printf(GetString(STR_SHELL_WARNING_PREFIX), text);
2099     return;
2100     }
2101     char str[256];
2102     sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text);
2103     BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, GetString(STR_OK_BUTTON), NULL, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT);
2104     alert->Go();
2105     }
2106    
2107    
2108     /*
2109     * Display choice alert
2110     */
2111    
2112     bool ChoiceAlert(const char *text, const char *pos, const char *neg)
2113     {
2114     char str[256];
2115     sprintf(str, GetString(STR_GUI_WARNING_PREFIX), text);
2116     BAlert *alert = new BAlert(GetString(STR_WARNING_ALERT_TITLE), str, pos, neg, NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT);
2117     return alert->Go() == 0;
2118     }