ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/BeOS/main_beos.cpp
Revision: 1.15
Committed: 2004-11-22T21:22:58Z (19 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.14: +4 -3 lines
Log Message:
new SheepShaver globals layout

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