ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/BeOS/main_beos.cpp
Revision: 1.13
Committed: 2004-07-03T10:39:05Z (19 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.12: +2 -0 lines
Log Message:
Introducce TimebaseSpeed which represents exact timebase-frequency instead
of supposing it to be (BusClockSpeed/4), which is no longer true on G5 et al.

File Contents

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