ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp
Revision: 1.1.1.1 (vendor branch)
Committed: 1999-10-03T14:16:26Z (25 years, 2 months ago) by cebix
Branch: cebix
CVS Tags: release-0_7-2, snapshot-21101999, start, snapshot-22121999, release-0_8-1, snapshot-02111999
Changes since 1.1: +0 -0 lines
Log Message:
Imported sources

File Contents

# Content
1 /*
2 * pwoerrom_cpu.cpp - Using the 680x0 emulator in PowerMac ROMs for Basilisk II
3 *
4 * Basilisk II (C) 1997-1999 Christian Bauer
5 */
6
7 #include <unistd.h>
8 #include <signal.h>
9 #include <stdlib.h>
10
11 #include <AppKit.h>
12 #include <KernelKit.h>
13 #include <StorageKit.h>
14
15 #include "sysdeps.h"
16 #include "cpu_emulation.h"
17 #include "main.h"
18 #include "emul_op.h"
19 #include "prefs.h"
20 #include "user_strings.h"
21
22 #include "sheep_driver.h"
23
24 #define DEBUG 0
25 #include "debug.h"
26
27 // Save FP regs in Execute68k()?
28 #define SAVE_FP_EXEC_68K 0
29
30
31 // Constants
32 const char ROM_FILE_NAME[] = "PowerROM";
33 const char KERNEL_AREA_NAME[] = "Macintosh Kernel Data";
34 const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache";
35
36 const uint32 ROM_BASE = 0x40800000; // Base address of ROM
37 const uint32 ROM_SIZE = 0x00400000; // Size of ROM file
38 const uint32 ROM_AREA_SIZE = 0x00500000; // Size of ROM area
39
40 const uint32 DR_CACHE_BASE = 0x69000000; // Address of DR cache
41 const uint32 DR_CACHE_SIZE = 0x80000; // Size of DR Cache
42
43 const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack
44
45 // PowerPC opcodes
46 const uint32 POWERPC_NOP = 0x60000000;
47 const uint32 POWERPC_ILLEGAL = 0x00000000;
48 const uint32 POWERPC_BLR = 0x4e800020;
49 const uint32 POWERPC_BCTR = 0x4e800420;
50
51 // Extra Low Memory Globals
52 #define MODE_68K 0 // 68k emulator active
53 #define MODE_EMUL_OP 1 // Within EMUL_OP routine
54
55 #define XLM_RESET_STACK 0x2800 // Reset stack pointer
56 #define XLM_KERNEL_DATA 0x2804 // Pointer to Kernel Data
57 #define XLM_TOC 0x2808 // TOC pointer of emulator
58 #define XLM_RUN_MODE 0x2810 // Current run mode, see enum above
59 #define XLM_68K_R25 0x2814 // Contents of the 68k emulator's r25 (which contains the interrupt level), saved upon entering EMUL_OP mode, used by Execute68k() and the USR1 signal handler
60 #define XLM_IRQ_NEST 0x2818 // Interrupt disable nesting counter (>0: disabled)
61 #define XLM_PVR 0x281c // Theoretical PVR
62 #define XLM_EMUL_RETURN_PROC 0x2824 // Pointer to EMUL_RETURN routine
63 #define XLM_EXEC_RETURN_PROC 0x2828 // Pointer to EXEC_RETURN routine
64 #define XLM_EMUL_OP_PROC 0x282c // Pointer to EMUL_OP routine
65 #define XLM_EMUL_RETURN_STACK 0x2830 // Stack pointer for EMUL_RETURN
66
67
68 // RAM and ROM pointers
69 uint32 RAMBaseMac; // RAM base (Mac address space)
70 uint8 *RAMBaseHost; // RAM base (host address space)
71 uint32 RAMSize; // Size of RAM
72 uint32 ROMBaseMac; // ROM base (Mac address space)
73 uint8 *ROMBaseHost; // ROM base (host address space)
74 uint32 ROMSize; // Size of ROM
75
76
77 // Emulator Data
78 struct EmulatorData {
79 uint32 v[0x400];
80 };
81
82
83 // Kernel Data
84 struct KernelData {
85 uint32 v[0x400];
86 EmulatorData ed;
87 };
88
89
90 // Exceptions
91 class file_open_error {};
92 class file_read_error {};
93 class rom_size_error {};
94
95
96 // Global variables
97 static void *TOC; // TOC pointer
98 static uint32 PVR; // Theoretical PVR
99 static int64 CPUClockSpeed; // Processor clock speed (Hz)
100 static int64 BusClockSpeed; // Bus clock speed (Hz)
101 static system_info SysInfo; // System information
102
103 static area_id kernel_area = -1; // Kernel Data area ID
104 static KernelData *kernel_data = NULL; // Pointer to Kernel Data
105 static uint32 KernelDataAddr; // Address of Kernel Data
106 static EmulatorData *emulator_data = NULL;
107 static area_id dr_cache_area; // DR Cache area ID
108 static uint32 DRCacheAddr; // Address of DR Cache
109
110 static struct sigaction sigusr1_action; // Interrupt signal (of emulator thread)
111 static bool ReadyForSignals = false; // Flag: emul_thread ready to receive signals
112
113
114 // Prototypes
115 static void sigusr1_handler(int sig, void *arg, vregs *r);
116
117 // From main_beos.cpp
118 extern int sheep_fd; // fd of sheep driver
119 extern thread_id emul_thread; // Emulator thread
120
121
122 /*
123 * Load ROM file (upper 3MB)
124 *
125 * file_open_error: Cannot open ROM file (nor use built-in ROM)
126 * file_read_error: Cannot read ROM file
127 */
128
129 // Decode LZSS data
130 static void decode_lzss(const uint8 *src, uint8 *dest, int size)
131 {
132 char dict[0x1000];
133 int run_mask = 0, dict_idx = 0xfee;
134 for (;;) {
135 if (run_mask < 0x100) {
136 // Start new run
137 if (--size < 0)
138 break;
139 run_mask = *src++ | 0xff00;
140 }
141 bool bit = run_mask & 1;
142 run_mask >>= 1;
143 if (bit) {
144 // Verbatim copy
145 if (--size < 0)
146 break;
147 int c = *src++;
148 dict[dict_idx++] = c;
149 *dest++ = c;
150 dict_idx &= 0xfff;
151 } else {
152 // Copy from dictionary
153 if (--size < 0)
154 break;
155 int idx = *src++;
156 if (--size < 0)
157 break;
158 int cnt = *src++;
159 idx |= (cnt << 4) & 0xf00;
160 cnt = (cnt & 0x0f) + 3;
161 while (cnt--) {
162 char c = dict[idx++];
163 dict[dict_idx++] = c;
164 *dest++ = c;
165 idx &= 0xfff;
166 dict_idx &= 0xfff;
167 }
168 }
169 }
170 }
171
172 static void load_rom(void)
173 {
174 // Get rom file path from preferences
175 const char *rom_path = PrefsFindString("powerrom");
176
177 // Try to open ROM file
178 BFile file(rom_path ? rom_path : ROM_FILE_NAME, B_READ_ONLY);
179 if (file.InitCheck() != B_NO_ERROR) {
180
181 // Failed, then ask sheep driver for ROM
182 uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work
183 ssize_t actual = read(sheep_fd, (void *)rom, ROM_SIZE);
184 if (actual == ROM_SIZE) {
185 // Copy upper 3MB
186 memcpy((void *)(ROM_BASE + 0x100000), rom + 0x100000, ROM_SIZE - 0x100000);
187 delete[] rom;
188 return;
189 } else
190 throw file_open_error();
191 }
192
193 printf(GetString(STR_READING_ROM_FILE));
194
195 // Get file size
196 off_t rom_size = 0;
197 file.GetSize(&rom_size);
198
199 uint8 *rom = new uint8[ROM_SIZE]; // Reading directly into the area doesn't work
200 ssize_t actual = file.Read((void *)rom, ROM_SIZE);
201 if (actual == ROM_SIZE) {
202 // Plain ROM image, copy upper 3MB
203 memcpy((void *)(ROM_BASE + 0x100000), rom + 0x100000, ROM_SIZE - 0x100000);
204 delete[] rom;
205 } else {
206 if (strncmp((char *)rom, "<CHRP-BOOT>", 11) == 0) {
207 // CHRP compressed ROM image
208 D(bug("CHRP ROM image\n"));
209 uint32 lzss_offset, lzss_size;
210
211 char *s = strstr((char *)rom, "constant lzss-offset");
212 if (s == NULL)
213 throw rom_size_error();
214 s -= 7;
215 if (sscanf(s, "%06lx", &lzss_offset) != 1)
216 throw rom_size_error();
217 s = strstr((char *)rom, "constant lzss-size");
218 if (s == NULL)
219 throw rom_size_error();
220 s -= 7;
221 if (sscanf(s, "%06lx", &lzss_size) != 1)
222 throw rom_size_error();
223 D(bug("Offset of compressed data: %08lx\n", lzss_offset));
224 D(bug("Size of compressed data: %08lx\n", lzss_size));
225
226 D(bug("Uncompressing ROM...\n"));
227 uint8 *decoded = new uint8[ROM_SIZE];
228 decode_lzss(rom + lzss_offset, decoded, lzss_size);
229 memcpy((void *)(ROM_BASE + 0x100000), decoded + 0x100000, ROM_SIZE - 0x100000);
230 delete[] decoded;
231 delete[] rom;
232 } else if (rom_size != 4*1024*1024)
233 throw rom_size_error();
234 else
235 throw file_read_error();
236 }
237 }
238
239
240 /*
241 * Patch PowerMac ROM
242 */
243
244 // ROM type
245 enum {
246 ROMTYPE_TNT,
247 ROMTYPE_ALCHEMY,
248 ROMTYPE_ZANZIBAR,
249 ROMTYPE_GAZELLE,
250 ROMTYPE_NEWWORLD
251 };
252 static int ROMType;
253
254 // Nanokernel boot routine patches
255 static bool patch_nanokernel_boot(void)
256 {
257 uint32 *lp;
258 int i;
259
260 // Patch ConfigInfo
261 lp = (uint32 *)(ROM_BASE + 0x30d000);
262 lp[0x9c >> 2] = KernelDataAddr; // LA_InfoRecord
263 lp[0xa0 >> 2] = KernelDataAddr; // LA_KernelData
264 lp[0xa4 >> 2] = KernelDataAddr + 0x1000;// LA_EmulatorData
265 lp[0xa8 >> 2] = ROM_BASE + 0x480000; // LA_DispatchTable
266 lp[0xac >> 2] = ROM_BASE + 0x460000; // LA_EmulatorCode
267 lp[0x360 >> 2] = 0; // Physical RAM base (? on NewWorld ROM, this contains -1)
268 lp[0xfd8 >> 2] = ROM_BASE + 0x2a; // 68k reset vector
269
270 // Skip SR/BAT/SDR init
271 if (ROMType == ROMTYPE_GAZELLE || ROMType == ROMTYPE_NEWWORLD) {
272 lp = (uint32 *)(ROM_BASE + 0x310000);
273 *lp++ = POWERPC_NOP;
274 *lp = 0x38000000;
275 }
276 static const uint32 sr_init_loc[] = {0x3101b0, 0x3101b0, 0x3101b0, 0x3101ec, 0x310200};
277 lp = (uint32 *)(ROM_BASE + 0x310008);
278 *lp = 0x48000000 | (sr_init_loc[ROMType] - 8) & 0xffff; // b ROM_BASE+0x3101b0
279 lp = (uint32 *)(ROM_BASE + sr_init_loc[ROMType]);
280 *lp++ = 0x80200000 + XLM_KERNEL_DATA; // lwz r1,(pointer to Kernel Data)
281 *lp++ = 0x3da0dead; // lis r13,0xdead (start of kernel memory)
282 *lp++ = 0x3dc00010; // lis r14,0x0010 (size of page table)
283 *lp = 0x3de00010; // lis r15,0x0010 (size of kernel memory)
284
285 // Don't read PVR
286 static const uint32 pvr_loc[] = {0x3103b0, 0x3103b4, 0x3103b4, 0x310400, 0x310438};
287 lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]);
288 *lp = 0x81800000 + XLM_PVR; // lwz r12,(theoretical PVR)
289
290 // Set CPU specific data (even if ROM doesn't have support for that CPU)
291 lp = (uint32 *)(ROM_BASE + pvr_loc[ROMType]);
292 if (ntohl(lp[6]) != 0x2c0c0001)
293 return false;
294 uint32 ofs = lp[7] & 0xffff;
295 lp[8] = (lp[8] & 0xffff) | 0x48000000; // beq -> b
296 uint32 loc = (lp[8] & 0xffff) + (uint32)(lp+8) - ROM_BASE;
297 lp = (uint32 *)(ROM_BASE + ofs + 0x310000);
298 switch (PVR >> 16) {
299 case 1: // 601
300 lp[0] = 0x1000; // Page size
301 lp[1] = 0x8000; // Data cache size
302 lp[2] = 0x8000; // Inst cache size
303 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
304 lp[4] = 0x00010040; // Unified caches/Inst cache line size
305 lp[5] = 0x00400020; // Data cache line size/Data cache block size touch
306 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
307 lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc
308 lp[8] = 0x01000002; // TLB total size/TLB assoc
309 break;
310 case 3: // 603
311 lp[0] = 0x1000; // Page size
312 lp[1] = 0x2000; // Data cache size
313 lp[2] = 0x2000; // Inst cache size
314 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
315 lp[4] = 0x00000020; // Unified caches/Inst cache line size
316 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
317 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
318 lp[7] = 0x00020002; // Inst cache assoc/Data cache assoc
319 lp[8] = 0x00400002; // TLB total size/TLB assoc
320 break;
321 case 4: // 604
322 lp[0] = 0x1000; // Page size
323 lp[1] = 0x4000; // Data cache size
324 lp[2] = 0x4000; // Inst cache size
325 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
326 lp[4] = 0x00000020; // Unified caches/Inst cache line size
327 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
328 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
329 lp[7] = 0x00040004; // Inst cache assoc/Data cache assoc
330 lp[8] = 0x00800002; // TLB total size/TLB assoc
331 break;
332 // case 5: // 740?
333 case 6: // 603e
334 case 7: // 603ev
335 lp[0] = 0x1000; // Page size
336 lp[1] = 0x4000; // Data cache size
337 lp[2] = 0x4000; // Inst cache size
338 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
339 lp[4] = 0x00000020; // Unified caches/Inst cache line size
340 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
341 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
342 lp[7] = 0x00040004; // Inst cache assoc/Data cache assoc
343 lp[8] = 0x00400002; // TLB total size/TLB assoc
344 break;
345 case 8: // 750
346 lp[0] = 0x1000; // Page size
347 lp[1] = 0x8000; // Data cache size
348 lp[2] = 0x8000; // Inst cache size
349 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
350 lp[4] = 0x00000020; // Unified caches/Inst cache line size
351 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
352 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
353 lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc
354 lp[8] = 0x00800002; // TLB total size/TLB assoc
355 break;
356 case 9: // 604e
357 case 10: // 604ev5
358 lp[0] = 0x1000; // Page size
359 lp[1] = 0x8000; // Data cache size
360 lp[2] = 0x8000; // Inst cache size
361 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
362 lp[4] = 0x00000020; // Unified caches/Inst cache line size
363 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
364 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
365 lp[7] = 0x00040004; // Inst cache assoc/Data cache assoc
366 lp[8] = 0x00800002; // TLB total size/TLB assoc
367 break;
368 // case 11: // X704?
369 case 12: // ???
370 lp[0] = 0x1000; // Page size
371 lp[1] = 0x8000; // Data cache size
372 lp[2] = 0x8000; // Inst cache size
373 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
374 lp[4] = 0x00000020; // Unified caches/Inst cache line size
375 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
376 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
377 lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc
378 lp[8] = 0x00800002; // TLB total size/TLB assoc
379 break;
380 case 13: // ???
381 lp[0] = 0x1000; // Page size
382 lp[1] = 0x8000; // Data cache size
383 lp[2] = 0x8000; // Inst cache size
384 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
385 lp[4] = 0x00000020; // Unified caches/Inst cache line size
386 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
387 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
388 lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc
389 lp[8] = 0x01000004; // TLB total size/TLB assoc
390 break;
391 // case 50: // 821
392 // case 80: // 860
393 case 96: // ???
394 lp[0] = 0x1000; // Page size
395 lp[1] = 0x8000; // Data cache size
396 lp[2] = 0x8000; // Inst cache size
397 lp[3] = 0x00200020; // Coherency block size/Reservation granule size
398 lp[4] = 0x00010020; // Unified caches/Inst cache line size
399 lp[5] = 0x00200020; // Data cache line size/Data cache block size touch
400 lp[6] = 0x00200020; // Inst cache block size/Data cache block size
401 lp[7] = 0x00080008; // Inst cache assoc/Data cache assoc
402 lp[8] = 0x00800004; // TLB total size/TLB assoc
403 break;
404 default:
405 printf("WARNING: Unknown CPU type\n");
406 break;
407 }
408
409 // Don't set SPRG3, don't test MQ
410 lp = (uint32 *)(ROM_BASE + loc + 0x20);
411 *lp++ = POWERPC_NOP;
412 lp++;
413 *lp++ = POWERPC_NOP;
414 lp++;
415 *lp = POWERPC_NOP;
416
417 // Don't read MSR
418 lp = (uint32 *)(ROM_BASE + loc + 0x40);
419 *lp = 0x39c00000; // li r14,0
420
421 // Don't write to DEC
422 lp = (uint32 *)(ROM_BASE + loc + 0x70);
423 *lp++ = POWERPC_NOP;
424 loc = (lp[0] & 0xffff) + (uint32)lp - ROM_BASE;
425
426 // Don't set SPRG3
427 lp = (uint32 *)(ROM_BASE + loc + 0x2c);
428 *lp = POWERPC_NOP;
429
430 // Don't read PVR
431 static const uint32 pvr_ofs[] = {0x138, 0x138, 0x138, 0x140, 0x148};
432 lp = (uint32 *)(ROM_BASE + loc + pvr_ofs[ROMType]);
433 *lp = 0x82e00000 + XLM_PVR; // lwz r23,(theoretical PVR)
434 lp = (uint32 *)(ROM_BASE + loc + 0x170);
435 if (*lp == 0x7eff42a6) // NewWorld ROM
436 *lp = 0x82e00000 + XLM_PVR; // lwz r23,(theoretical PVR)
437 lp = (uint32 *)(ROM_BASE + 0x313134);
438 if (*lp == 0x7e5f42a6)
439 *lp = 0x82400000 + XLM_PVR; // lwz r18,(theoretical PVR)
440 lp = (uint32 *)(ROM_BASE + 0x3131f4);
441 if (*lp == 0x7e5f42a6) // NewWorld ROM
442 *lp = 0x82400000 + XLM_PVR; // lwz r18,(theoretical PVR)
443
444 // Don't read SDR1
445 static const uint32 sdr1_ofs[] = {0x174, 0x174, 0x174, 0x17c, 0x19c};
446 lp = (uint32 *)(ROM_BASE + loc + sdr1_ofs[ROMType]);
447 *lp++ = 0x3d00dead; // lis r8,0xdead (pointer to page table)
448 *lp++ = 0x3ec0001f; // lis r22,0x001f (size of page table)
449 *lp = POWERPC_NOP;
450
451 // Don't clear page table
452 static const uint32 pgtb_ofs[] = {0x198, 0x198, 0x198, 0x1a0, 0x1c4};
453 lp = (uint32 *)(ROM_BASE + loc + pgtb_ofs[ROMType]);
454 *lp = POWERPC_NOP;
455
456 // Don't invalidate TLB
457 static const uint32 tlb_ofs[] = {0x1a0, 0x1a0, 0x1a0, 0x1a8, 0x1cc};
458 lp = (uint32 *)(ROM_BASE + loc + tlb_ofs[ROMType]);
459 *lp = POWERPC_NOP;
460
461 // Don't create RAM descriptor table
462 static const uint32 desc_ofs[] = {0x350, 0x350, 0x350, 0x358, 0x37c};
463 lp = (uint32 *)(ROM_BASE + loc + desc_ofs[ROMType]);
464 *lp = POWERPC_NOP;
465
466 // Don't load SRs and BATs
467 static const uint32 sr_ofs[] = {0x3d8, 0x3d8, 0x3d8, 0x3e0, 0x404};
468 lp = (uint32 *)(ROM_BASE + loc + sr_ofs[ROMType]);
469 *lp = POWERPC_NOP;
470
471 // Don't mess with SRs
472 static const uint32 sr2_ofs[] = {0x312118, 0x312118, 0x312118, 0x312118, 0x3121b4};
473 lp = (uint32 *)(ROM_BASE + sr2_ofs[ROMType]);
474 *lp = POWERPC_BLR;
475
476 // Don't check performance monitor
477 static const uint32 pm_ofs[] = {0x313148, 0x313148, 0x313148, 0x313148, 0x313218};
478 lp = (uint32 *)(ROM_BASE + pm_ofs[ROMType]);
479 while (*lp != 0x7e58eba6) lp++;
480 *lp++ = POWERPC_NOP;
481 while (*lp != 0x7e78eaa6) lp++;
482 *lp++ = POWERPC_NOP;
483 while (*lp != 0x7e59eba6) lp++;
484 *lp++ = POWERPC_NOP;
485 while (*lp != 0x7e79eaa6) lp++;
486 *lp++ = POWERPC_NOP;
487 while (*lp != 0x7e5aeba6) lp++;
488 *lp++ = POWERPC_NOP;
489 while (*lp != 0x7e7aeaa6) lp++;
490 *lp++ = POWERPC_NOP;
491 while (*lp != 0x7e5beba6) lp++;
492 *lp++ = POWERPC_NOP;
493 while (*lp != 0x7e7beaa6) lp++;
494 *lp++ = POWERPC_NOP;
495 while (*lp != 0x7e5feba6) lp++;
496 *lp++ = POWERPC_NOP;
497 while (*lp != 0x7e7feaa6) lp++;
498 *lp++ = POWERPC_NOP;
499 while (*lp != 0x7e5ceba6) lp++;
500 *lp++ = POWERPC_NOP;
501 while (*lp != 0x7e7ceaa6) lp++;
502 *lp++ = POWERPC_NOP;
503 while (*lp != 0x7e5deba6) lp++;
504 *lp++ = POWERPC_NOP;
505 while (*lp != 0x7e7deaa6) lp++;
506 *lp++ = POWERPC_NOP;
507 while (*lp != 0x7e5eeba6) lp++;
508 *lp++ = POWERPC_NOP;
509 while (*lp != 0x7e7eeaa6) lp++;
510 *lp++ = POWERPC_NOP;
511
512 // Jump to 68k emulator
513 static const uint32 jump68k_ofs[] = {0x40c, 0x40c, 0x40c, 0x414, 0x438};
514 lp = (uint32 *)(ROM_BASE + loc + jump68k_ofs[ROMType]);
515 *lp++ = 0x80610634; // lwz r3,0x0634(r1) (pointer to Emulator Data)
516 *lp++ = 0x8081119c; // lwz r4,0x119c(r1) (pointer to opcode table)
517 *lp++ = 0x80011184; // lwz r0,0x1184(r1) (pointer to emulator entry)
518 *lp++ = 0x7c0903a6; // mtctr r0
519 *lp = POWERPC_BCTR;
520 return true;
521 }
522
523 // 68k emulator patches
524 static bool patch_68k_emul(void)
525 {
526 uint32 *lp;
527 uint32 base;
528
529 // Overwrite twi instructions
530 static const uint32 twi_loc[] = {0x36e680, 0x36e6c0, 0x36e6c0, 0x36e6c0, 0x36e740};
531 base = twi_loc[ROMType];
532 lp = (uint32 *)(ROM_BASE + base);
533 *lp++ = 0x48000000 + 0x36f900 - base; // b 0x36f900 (Emulator start)
534 *lp++ = POWERPC_ILLEGAL;
535 *lp++ = 0x48000000 + 0x36fb00 - base - 8; // b 0x36fb00 (Reset opcode)
536 *lp++ = POWERPC_ILLEGAL;
537 *lp++ = POWERPC_ILLEGAL;
538 *lp++ = POWERPC_ILLEGAL;
539 *lp++ = POWERPC_ILLEGAL;
540 *lp++ = POWERPC_ILLEGAL;
541 *lp++ = POWERPC_ILLEGAL;
542 *lp++ = POWERPC_ILLEGAL;
543 *lp++ = POWERPC_ILLEGAL;
544 *lp++ = POWERPC_ILLEGAL;
545 *lp++ = POWERPC_ILLEGAL;
546 *lp++ = POWERPC_ILLEGAL;
547 *lp++ = POWERPC_ILLEGAL;
548 *lp++ = POWERPC_ILLEGAL;
549
550 // Set reset stack pointer
551 lp = (uint32 *)(ROM_BASE + base + 0xf0);
552 *lp++ = 0x80200000 + XLM_RESET_STACK; // lwz r1,XLM_RESET_STACK
553
554 // Install EXEC_RETURN and EMUL_OP opcodes
555 lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EXEC_RETURN << 3));
556 *lp++ = 0x80000000 + XLM_EXEC_RETURN_PROC; // lwz r0,XLM_EXEC_RETURN_PROC
557 *lp++ = 0x4bfb6ffc; // b 0x36f800
558 for (int i=0; i<M68K_EMUL_OP_MAX-M68K_EMUL_BREAK; i++) {
559 *lp++ = 0x38a00000 + i + M68K_EMUL_BREAK; // li r5,M68K_EMUL_OP_*
560 *lp++ = 0x4bfb6ffc - i*8; // b 0x36f808
561 }
562
563 // Special handling for M68K_EMUL_OP_SHUTDOWN because Basilisk II is running
564 // on the 68k stack and simply quitting would delete the RAM area leaving
565 // the stack pointer in unaccessible memory
566 lp = (uint32 *)(ROM_BASE + 0x380000 + (M68K_EMUL_OP_SHUTDOWN << 3));
567 *lp++ = 0x80000000 + XLM_EMUL_RETURN_PROC; // lwz r0,XLM_EMUL_RETURN_PROC
568 *lp++ = 0x4bfb6ffc - (M68K_EMUL_OP_SHUTDOWN - M68K_EXEC_RETURN) * 8; // b 0x36f800
569
570 // Extra routines for EMUL_RETURN/EXEC_RETURN/EMUL_OP
571 lp = (uint32 *)(ROM_BASE + 0x36f800);
572 *lp++ = 0x7c0803a6; // mtlr r0
573 *lp++ = 0x4e800020; // blr
574
575 *lp++ = 0x80000000 + XLM_EMUL_OP_PROC; // lwz r0,XLM_EMUL_OP_PROC
576 *lp++ = 0x7c0803a6; // mtlr r0
577 *lp++ = 0x4e800020; // blr
578
579 // Extra routine for 68k emulator start
580 lp = (uint32 *)(ROM_BASE + 0x36f900);
581 *lp++ = 0x7c2903a6; // mtctr r1
582 *lp++ = 0x80200000 + XLM_IRQ_NEST; // lwz r1,XLM_IRQ_NEST
583 *lp++ = 0x38210001; // addi r1,r1,1
584 *lp++ = 0x90200000 + XLM_IRQ_NEST; // stw r1,XLM_IRQ_NEST
585 *lp++ = 0x80200000 + XLM_KERNEL_DATA;// lwz r1,XLM_KERNEL_DATA
586 *lp++ = 0x90c10018; // stw r6,0x18(r1)
587 *lp++ = 0x7cc902a6; // mfctr r6
588 *lp++ = 0x90c10004; // stw r6,$0004(r1)
589 *lp++ = 0x80c1065c; // lwz r6,$065c(r1)
590 *lp++ = 0x90e6013c; // stw r7,$013c(r6)
591 *lp++ = 0x91060144; // stw r8,$0144(r6)
592 *lp++ = 0x9126014c; // stw r9,$014c(r6)
593 *lp++ = 0x91460154; // stw r10,$0154(r6)
594 *lp++ = 0x9166015c; // stw r11,$015c(r6)
595 *lp++ = 0x91860164; // stw r12,$0164(r6)
596 *lp++ = 0x91a6016c; // stw r13,$016c(r6)
597 *lp++ = 0x7da00026; // mfcr r13
598 *lp++ = 0x80e10660; // lwz r7,$0660(r1)
599 *lp++ = 0x7d8802a6; // mflr r12
600 *lp++ = 0x50e74001; // rlwimi. r7,r7,8,$80000000
601 *lp++ = 0x814105f0; // lwz r10,0x05f0(r1)
602 *lp++ = 0x7d4803a6; // mtlr r10
603 *lp++ = 0x7d8a6378; // mr r10,r12
604 *lp++ = 0x3d600002; // lis r11,0x0002
605 *lp++ = 0x616bf072; // ori r11,r11,0xf072 (MSR)
606 *lp++ = 0x50e7deb4; // rlwimi r7,r7,27,$00000020
607 *lp++ = 0x4e800020; // blr
608
609 // Extra routine for Reset opcode
610 lp = (uint32 *)(ROM_BASE + 0x36fc00);
611 *lp++ = 0x7c2903a6; // mtctr r1
612 *lp++ = 0x80200000 + XLM_IRQ_NEST; // lwz r1,XLM_IRQ_NEST
613 *lp++ = 0x38210001; // addi r1,r1,1
614 *lp++ = 0x90200000 + XLM_IRQ_NEST; // stw r1,XLM_IRQ_NEST
615 *lp++ = 0x80200000 + XLM_KERNEL_DATA;// lwz r1,XLM_KERNEL_DATA
616 *lp++ = 0x90c10018; // stw r6,0x18(r1)
617 *lp++ = 0x7cc902a6; // mfctr r6
618 *lp++ = 0x90c10004; // stw r6,$0004(r1)
619 *lp++ = 0x80c1065c; // lwz r6,$065c(r1)
620 *lp++ = 0x90e6013c; // stw r7,$013c(r6)
621 *lp++ = 0x91060144; // stw r8,$0144(r6)
622 *lp++ = 0x9126014c; // stw r9,$014c(r6)
623 *lp++ = 0x91460154; // stw r10,$0154(r6)
624 *lp++ = 0x9166015c; // stw r11,$015c(r6)
625 *lp++ = 0x91860164; // stw r12,$0164(r6)
626 *lp++ = 0x91a6016c; // stw r13,$016c(r6)
627 *lp++ = 0x7da00026; // mfcr r13
628 *lp++ = 0x80e10660; // lwz r7,$0660(r1)
629 *lp++ = 0x7d8802a6; // mflr r12
630 *lp++ = 0x50e74001; // rlwimi. r7,r7,8,$80000000
631 *lp++ = 0x814105f4; // lwz r10,0x05f8(r1)
632 *lp++ = 0x7d4803a6; // mtlr r10
633 *lp++ = 0x7d8a6378; // mr r10,r12
634 *lp++ = 0x3d600002; // lis r11,0x0002
635 *lp++ = 0x616bf072; // ori r11,r11,0xf072 (MSR)
636 *lp++ = 0x50e7deb4; // rlwimi r7,r7,27,$00000020
637 *lp++ = 0x4e800020; // blr
638
639 // Patch DR emulator to jump to right address when an interrupt occurs
640 lp = (uint32 *)(ROM_BASE + 0x370000);
641 while (lp < (uint32 *)(ROM_BASE + 0x380000)) {
642 if (*lp == 0x4ca80020) // bclr 5,8
643 goto dr_found;
644 lp++;
645 }
646 D(bug("DR emulator patch location not found\n"));
647 return false;
648 dr_found:
649 lp++;
650 *lp = 0x48000000 + 0xf000 - ((uint32)lp & 0xffff); // b DR_CACHE_BASE+0x1f000
651 lp = (uint32 *)(ROM_BASE + 0x37f000);
652 *lp++ = 0x3c000000 + ((ROM_BASE + 0x46d0a4) >> 16); // lis r0,xxx
653 *lp++ = 0x60000000 + ((ROM_BASE + 0x46d0a4) & 0xffff); // ori r0,r0,xxx
654 *lp++ = 0x7c0903a6; // mtctr r0
655 *lp = POWERPC_BCTR; // bctr
656 return true;
657 }
658
659 // Nanokernel patches
660 static bool patch_nanokernel(void)
661 {
662 uint32 *lp;
663
664 // Patch 68k emulator trap routine
665 lp = (uint32 *)(ROM_BASE + 0x312994); // Always restore FPU state
666 while (*lp != 0x39260040) lp++;
667 lp--;
668 *lp = 0x48000441; // bl 0x00312dd4
669 lp = (uint32 *)(ROM_BASE + 0x312dd8); // Don't modify MSR to turn on FPU
670 while (*lp != 0x810600e4) lp++;
671 lp--;
672 *lp++ = POWERPC_NOP;
673 lp += 2;
674 *lp++ = POWERPC_NOP;
675 lp++;
676 *lp++ = POWERPC_NOP;
677 *lp++ = POWERPC_NOP;
678 *lp = POWERPC_NOP;
679
680 // Patch trap return routine
681 lp = (uint32 *)(ROM_BASE + 0x312c20);
682 while (*lp != 0x7d5a03a6) lp++;
683 *lp++ = 0x7d4903a6; // mtctr r10
684 *lp++ = 0x7daff120; // mtcr r13
685 *lp++ = 0x48000000 + 0x8000 - ((uint32)lp & 0xffff); // b ROM_BASE+0x318000
686 uint32 xlp = (uint32)lp & 0xffff;
687
688 lp = (uint32 *)(ROM_BASE + 0x312c50); // Replace rfi
689 while (*lp != 0x4c000064) lp++;
690 *lp = POWERPC_BCTR;
691
692 lp = (uint32 *)(ROM_BASE + 0x318000);
693 *lp++ = 0x81400000 + XLM_IRQ_NEST; // lwz r10,XLM_IRQ_NEST
694 *lp++ = 0x394affff; // subi r10,r10,1
695 *lp++ = 0x91400000 + XLM_IRQ_NEST; // stw r10,XLM_IRQ_NEST
696 *lp = 0x48000000 + ((xlp - 0x800c) & 0x03fffffc); // b ROM_BASE+0x312c2c
697 return true;
698 }
699
700 static bool patch_rom(void)
701 {
702 // Detect ROM type
703 if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot TNT", 8))
704 ROMType = ROMTYPE_TNT;
705 else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Alchemy", 12))
706 ROMType = ROMTYPE_ALCHEMY;
707 else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Zanzibar", 13))
708 ROMType = ROMTYPE_ZANZIBAR;
709 else if (!memcmp((void *)(ROM_BASE + 0x30d064), "Boot Gazelle", 12))
710 ROMType = ROMTYPE_GAZELLE;
711 else if (!memcmp((void *)(ROM_BASE + 0x30d064), "NewWorld", 8))
712 ROMType = ROMTYPE_NEWWORLD;
713 else
714 return false;
715
716 // Apply patches
717 if (!patch_nanokernel_boot()) return false;
718 if (!patch_68k_emul()) return false;
719 if (!patch_nanokernel()) return false;
720
721 // Copy 68k emulator to 2MB boundary
722 memcpy((void *)(ROM_BASE + ROM_SIZE), (void *)(ROM_BASE + ROM_SIZE - 0x100000), 0x100000);
723 return true;
724 }
725
726
727 /*
728 * Initialize 680x0 emulation
729 */
730
731 static asm void *get_toc(void)
732 {
733 mr r3,r2
734 blr
735 }
736
737 bool Init680x0(void)
738 {
739 char str[256];
740
741 // Mac address space = host address space
742 RAMBaseMac = (uint32)RAMBaseHost;
743 ROMBaseMac = (uint32)ROMBaseHost;
744
745 // Get TOC pointer
746 TOC = get_toc();
747
748 // Get system info
749 get_system_info(&SysInfo);
750 switch (SysInfo.cpu_type) {
751 case B_CPU_PPC_601:
752 PVR = 0x00010000;
753 break;
754 case B_CPU_PPC_603:
755 PVR = 0x00030000;
756 break;
757 case B_CPU_PPC_603e:
758 PVR = 0x00060000;
759 break;
760 case B_CPU_PPC_604:
761 PVR = 0x00040000;
762 break;
763 case B_CPU_PPC_604e:
764 PVR = 0x00090000;
765 break;
766 default:
767 PVR = 0x00040000;
768 break;
769 }
770 CPUClockSpeed = SysInfo.cpu_clock_speed;
771 BusClockSpeed = SysInfo.bus_clock_speed;
772
773 // Delete old areas
774 area_id old_kernel_area = find_area(KERNEL_AREA_NAME);
775 if (old_kernel_area > 0)
776 delete_area(old_kernel_area);
777 area_id old_dr_cache_area = find_area(DR_CACHE_AREA_NAME);
778 if (old_dr_cache_area > 0)
779 delete_area(old_dr_cache_area);
780
781 // Create area for Kernel Data
782 kernel_data = (KernelData *)0x68ffe000;
783 kernel_area = create_area(KERNEL_AREA_NAME, &kernel_data, B_EXACT_ADDRESS, 0x2000, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
784 if (kernel_area < 0) {
785 sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(kernel_area), kernel_area);
786 ErrorAlert(str);
787 return false;
788 }
789 emulator_data = &kernel_data->ed;
790 KernelDataAddr = (uint32)kernel_data;
791 D(bug("Kernel Data area %ld at %p, Emulator Data at %p\n", kernel_area, kernel_data, emulator_data));
792
793 // Load PowerMac ROM (upper 3MB)
794 try {
795 load_rom();
796 } catch (file_open_error) {
797 ErrorAlert(GetString(STR_NO_ROM_FILE_ERR));
798 return false;
799 } catch (file_read_error) {
800 ErrorAlert(GetString(STR_ROM_FILE_READ_ERR));
801 return false;
802 } catch (rom_size_error) {
803 ErrorAlert(GetString(STR_ROM_SIZE_ERR));
804 return false;
805 }
806
807 // Install ROM patches
808 if (!patch_rom()) {
809 ErrorAlert("Unsupported PowerMac ROM version");
810 return false;
811 }
812
813 // Create area for DR Cache
814 DRCacheAddr = DR_CACHE_BASE;
815 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);
816 if (dr_cache_area < 0) {
817 sprintf(str, GetString(STR_NO_KERNEL_DATA_ERR), strerror(dr_cache_area), dr_cache_area);
818 ErrorAlert(str);
819 return false;
820 }
821 D(bug("DR Cache area %ld at %p\n", dr_cache_area, DRCacheAddr));
822
823 // Initialize Kernel Data
824 memset(kernel_data, 0, sizeof(KernelData));
825 if (ROMType == ROMTYPE_NEWWORLD) {
826 kernel_data->v[0xc20 >> 2] = RAMSize;
827 kernel_data->v[0xc24 >> 2] = RAMSize;
828 kernel_data->v[0xc30 >> 2] = RAMSize;
829 kernel_data->v[0xc34 >> 2] = RAMSize;
830 kernel_data->v[0xc38 >> 2] = 0x00010020;
831 kernel_data->v[0xc3c >> 2] = 0x00200001;
832 kernel_data->v[0xc40 >> 2] = 0x00010000;
833 kernel_data->v[0xc50 >> 2] = RAMBaseMac;
834 kernel_data->v[0xc54 >> 2] = RAMSize;
835 kernel_data->v[0xf60 >> 2] = PVR;
836 kernel_data->v[0xf64 >> 2] = CPUClockSpeed;
837 kernel_data->v[0xf68 >> 2] = BusClockSpeed;
838 kernel_data->v[0xf6c >> 2] = CPUClockSpeed;
839 } else {
840 kernel_data->v[0xc80 >> 2] = RAMSize;
841 kernel_data->v[0xc84 >> 2] = RAMSize;
842 kernel_data->v[0xc90 >> 2] = RAMSize;
843 kernel_data->v[0xc94 >> 2] = RAMSize;
844 kernel_data->v[0xc98 >> 2] = 0x00010020;
845 kernel_data->v[0xc9c >> 2] = 0x00200001;
846 kernel_data->v[0xca0 >> 2] = 0x00010000;
847 kernel_data->v[0xcb0 >> 2] = RAMBaseMac;
848 kernel_data->v[0xcb4 >> 2] = RAMSize;
849 kernel_data->v[0xf80 >> 2] = PVR;
850 kernel_data->v[0xf84 >> 2] = CPUClockSpeed;
851 kernel_data->v[0xf88 >> 2] = BusClockSpeed;
852 kernel_data->v[0xf8c >> 2] = CPUClockSpeed;
853 }
854
855 // Initialize extra low memory
856 memset((void *)0x2000, 0, 0x1000);
857 *(uint32 *)XLM_RESET_STACK = 0x2000; // Reset stack pointer
858 *(KernelData **)XLM_KERNEL_DATA = kernel_data;// For trap replacement routines
859 *(void **)XLM_TOC = TOC; // TOC pointer of emulator
860 *(uint32 *)XLM_PVR = PVR; // Theoretical PVR
861
862 // Clear caches (as we loaded and patched code)
863 clear_caches((void *)ROM_BASE, ROM_AREA_SIZE, B_INVALIDATE_ICACHE | B_FLUSH_DCACHE);
864 return true;
865 }
866
867
868 /*
869 * Deinitialize 680x0 emulation
870 */
871
872 void Exit680x0(void)
873 {
874 // Delete DR Cache area
875 if (dr_cache_area >= 0)
876 delete_area(dr_cache_area);
877
878 // Delete Kernel Data area
879 if (kernel_area >= 0)
880 delete_area(kernel_area);
881 }
882
883
884 /*
885 * Quit emulator (must only be called from main thread)
886 */
887
888 asm void QuitEmulator(void)
889 {
890 lwz r0,XLM_EMUL_RETURN_PROC
891 mtlr r0
892 blr
893 }
894
895
896 /*
897 * Reset and start 680x0 emulation
898 */
899
900 static asm void jump_to_rom(register uint32 entry)
901 {
902 // Create stack frame
903 mflr r0
904 stw r0,8(r1)
905 mfcr r0
906 stw r0,4(r1)
907 stwu r1,-(56+19*4+18*8)(r1)
908
909 // Save PowerPC registers
910 stmw r13,56(r1)
911 stfd f14,56+19*4+0*8(r1)
912 stfd f15,56+19*4+1*8(r1)
913 stfd f16,56+19*4+2*8(r1)
914 stfd f17,56+19*4+3*8(r1)
915 stfd f18,56+19*4+4*8(r1)
916 stfd f19,56+19*4+5*8(r1)
917 stfd f20,56+19*4+6*8(r1)
918 stfd f21,56+19*4+7*8(r1)
919 stfd f22,56+19*4+8*8(r1)
920 stfd f23,56+19*4+9*8(r1)
921 stfd f24,56+19*4+10*8(r1)
922 stfd f25,56+19*4+11*8(r1)
923 stfd f26,56+19*4+12*8(r1)
924 stfd f27,56+19*4+13*8(r1)
925 stfd f28,56+19*4+14*8(r1)
926 stfd f29,56+19*4+15*8(r1)
927 stfd f30,56+19*4+16*8(r1)
928 stfd f31,56+19*4+17*8(r1)
929
930 // Move entry address to ctr, get pointer to Emulator Data
931 mtctr r3
932 lwz r3,emulator_data(r2)
933
934 // Skip over EMUL_RETURN routine and get its address
935 bl @1
936
937
938 /*
939 * EMUL_RETURN: Returned from emulator
940 */
941
942 // Restore PowerPC registers
943 lwz r1,XLM_EMUL_RETURN_STACK
944 lwz r2,XLM_TOC
945 lmw r13,56(r1)
946 lfd f14,56+19*4+0*8(r1)
947 lfd f15,56+19*4+1*8(r1)
948 lfd f16,56+19*4+2*8(r1)
949 lfd f17,56+19*4+3*8(r1)
950 lfd f18,56+19*4+4*8(r1)
951 lfd f19,56+19*4+5*8(r1)
952 lfd f20,56+19*4+6*8(r1)
953 lfd f21,56+19*4+7*8(r1)
954 lfd f22,56+19*4+8*8(r1)
955 lfd f23,56+19*4+9*8(r1)
956 lfd f24,56+19*4+10*8(r1)
957 lfd f25,56+19*4+11*8(r1)
958 lfd f26,56+19*4+12*8(r1)
959 lfd f27,56+19*4+13*8(r1)
960 lfd f28,56+19*4+14*8(r1)
961 lfd f29,56+19*4+15*8(r1)
962 lfd f30,56+19*4+16*8(r1)
963 lfd f31,56+19*4+17*8(r1)
964
965 // Exiting from 68k emulator
966 li r0,1
967 stw r0,XLM_IRQ_NEST
968 li r0,MODE_EMUL_OP
969 stw r0,XLM_RUN_MODE
970
971 // Return to caller of jump_to_rom()
972 lwz r0,56+19*4+18*8+8(r1)
973 mtlr r0
974 lwz r0,56+19*4+18*8+4(r1)
975 mtcrf 0xff,r0
976 addi r1,r1,56+19*4+18*8
977 blr
978
979
980 // Save address of EMUL_RETURN routine for 68k emulator patch
981 @1 mflr r0
982 stw r0,XLM_EMUL_RETURN_PROC
983
984 // Skip over EXEC_RETURN routine and get its address
985 bl @2
986
987
988 /*
989 * EXEC_RETURN: Returned from 68k routine executed with Execute68k()
990 */
991
992 // Save r25 (contains current 68k interrupt level)
993 stw r25,XLM_68K_R25
994
995 // Reentering EMUL_OP mode
996 li r0,MODE_EMUL_OP
997 stw r0,XLM_RUN_MODE
998
999 // Save 68k registers
1000 lwz r4,56+19*4+18*8+12(r1)
1001 stw r8,M68kRegisters.d[0](r4)
1002 stw r9,M68kRegisters.d[1](r4)
1003 stw r10,M68kRegisters.d[2](r4)
1004 stw r11,M68kRegisters.d[3](r4)
1005 stw r12,M68kRegisters.d[4](r4)
1006 stw r13,M68kRegisters.d[5](r4)
1007 stw r14,M68kRegisters.d[6](r4)
1008 stw r15,M68kRegisters.d[7](r4)
1009 stw r16,M68kRegisters.a[0](r4)
1010 stw r17,M68kRegisters.a[1](r4)
1011 stw r18,M68kRegisters.a[2](r4)
1012 stw r19,M68kRegisters.a[3](r4)
1013 stw r20,M68kRegisters.a[4](r4)
1014 stw r21,M68kRegisters.a[5](r4)
1015 stw r22,M68kRegisters.a[6](r4)
1016
1017 // Restore PowerPC registers
1018 lmw r13,56(r1)
1019 #if SAVE_FP_EXEC_68K
1020 lfd f14,56+19*4+0*8(r1)
1021 lfd f15,56+19*4+1*8(r1)
1022 lfd f16,56+19*4+2*8(r1)
1023 lfd f17,56+19*4+3*8(r1)
1024 lfd f18,56+19*4+4*8(r1)
1025 lfd f19,56+19*4+5*8(r1)
1026 lfd f20,56+19*4+6*8(r1)
1027 lfd f21,56+19*4+7*8(r1)
1028 lfd f22,56+19*4+8*8(r1)
1029 lfd f23,56+19*4+9*8(r1)
1030 lfd f24,56+19*4+10*8(r1)
1031 lfd f25,56+19*4+11*8(r1)
1032 lfd f26,56+19*4+12*8(r1)
1033 lfd f27,56+19*4+13*8(r1)
1034 lfd f28,56+19*4+14*8(r1)
1035 lfd f29,56+19*4+15*8(r1)
1036 lfd f30,56+19*4+16*8(r1)
1037 lfd f31,56+19*4+17*8(r1)
1038 #endif
1039
1040 // Return to caller
1041 lwz r0,56+19*4+18*8+8(r1)
1042 mtlr r0
1043 addi r1,r1,56+19*4+18*8
1044 blr
1045
1046
1047 // Stave address of EXEC_RETURN routine for 68k emulator patch
1048 @2 mflr r0
1049 stw r0,XLM_EXEC_RETURN_PROC
1050
1051 // Skip over EMUL_OP routine and get its address
1052 bl @3
1053
1054
1055 /*
1056 * EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
1057 *
1058 * 68k registers are stored in a M68kRegisters struct on the stack
1059 * which the native routine may read and modify
1060 */
1061
1062 // Save r25 (contains current 68k interrupt level)
1063 stw r25,XLM_68K_R25
1064
1065 // Entering EMUL_OP mode within 68k emulator
1066 li r0,MODE_EMUL_OP
1067 stw r0,XLM_RUN_MODE
1068
1069 // Create PowerPC stack frame, reserve space for M68kRegisters
1070 mr r3,r1
1071 subi r1,r1,56 // Fake "caller" frame
1072 rlwinm r1,r1,0,0,29 // Align stack
1073
1074 mfcr r0
1075 rlwinm r0,r0,0,11,8
1076 stw r0,4(r1)
1077 mfxer r0
1078 stw r0,16(r1)
1079 stw r2,12(r1)
1080 stwu r1,-(56+16*4+15*8)(r1)
1081 lwz r2,XLM_TOC
1082
1083 // Save 68k registers
1084 stw r8,56+M68kRegisters.d[0](r1)
1085 stw r9,56+M68kRegisters.d[1](r1)
1086 stw r10,56+M68kRegisters.d[2](r1)
1087 stw r11,56+M68kRegisters.d[3](r1)
1088 stw r12,56+M68kRegisters.d[4](r1)
1089 stw r13,56+M68kRegisters.d[5](r1)
1090 stw r14,56+M68kRegisters.d[6](r1)
1091 stw r15,56+M68kRegisters.d[7](r1)
1092 stw r16,56+M68kRegisters.a[0](r1)
1093 stw r17,56+M68kRegisters.a[1](r1)
1094 stw r18,56+M68kRegisters.a[2](r1)
1095 stw r19,56+M68kRegisters.a[3](r1)
1096 stw r20,56+M68kRegisters.a[4](r1)
1097 stw r21,56+M68kRegisters.a[5](r1)
1098 stw r22,56+M68kRegisters.a[6](r1)
1099 stw r3,56+M68kRegisters.a[7](r1)
1100 stfd f0,56+16*4+0*8(r1)
1101 stfd f1,56+16*4+1*8(r1)
1102 stfd f2,56+16*4+2*8(r1)
1103 stfd f3,56+16*4+3*8(r1)
1104 stfd f4,56+16*4+4*8(r1)
1105 stfd f5,56+16*4+5*8(r1)
1106 stfd f6,56+16*4+6*8(r1)
1107 stfd f7,56+16*4+7*8(r1)
1108 mffs f0
1109 stfd f8,56+16*4+8*8(r1)
1110 stfd f9,56+16*4+9*8(r1)
1111 stfd f10,56+16*4+10*8(r1)
1112 stfd f11,56+16*4+11*8(r1)
1113 stfd f12,56+16*4+12*8(r1)
1114 stfd f13,56+16*4+13*8(r1)
1115 stfd f0,56+16*4+14*8(r1)
1116
1117 // Execute native routine
1118 mr r3,r5
1119 addi r4,r1,56
1120 bl EmulOp
1121
1122 // Restore 68k registers
1123 lwz r8,56+M68kRegisters.d[0](r1)
1124 lwz r9,56+M68kRegisters.d[1](r1)
1125 lwz r10,56+M68kRegisters.d[2](r1)
1126 lwz r11,56+M68kRegisters.d[3](r1)
1127 lwz r12,56+M68kRegisters.d[4](r1)
1128 lwz r13,56+M68kRegisters.d[5](r1)
1129 lwz r14,56+M68kRegisters.d[6](r1)
1130 lwz r15,56+M68kRegisters.d[7](r1)
1131 lwz r16,56+M68kRegisters.a[0](r1)
1132 lwz r17,56+M68kRegisters.a[1](r1)
1133 lwz r18,56+M68kRegisters.a[2](r1)
1134 lwz r19,56+M68kRegisters.a[3](r1)
1135 lwz r20,56+M68kRegisters.a[4](r1)
1136 lwz r21,56+M68kRegisters.a[5](r1)
1137 lwz r22,56+M68kRegisters.a[6](r1)
1138 lwz r3,56+M68kRegisters.a[7](r1)
1139 lfd f13,56+16*4+14*8(r1)
1140 lfd f0,56+16*4+0*8(r1)
1141 lfd f1,56+16*4+1*8(r1)
1142 lfd f2,56+16*4+2*8(r1)
1143 lfd f3,56+16*4+3*8(r1)
1144 lfd f4,56+16*4+4*8(r1)
1145 lfd f5,56+16*4+5*8(r1)
1146 lfd f6,56+16*4+6*8(r1)
1147 lfd f7,56+16*4+7*8(r1)
1148 mtfsf 0xff,f13
1149 lfd f8,56+16*4+8*8(r1)
1150 lfd f9,56+16*4+9*8(r1)
1151 lfd f10,56+16*4+10*8(r1)
1152 lfd f11,56+16*4+11*8(r1)
1153 lfd f12,56+16*4+12*8(r1)
1154 lfd f13,56+16*4+13*8(r1)
1155
1156 // Delete PowerPC stack frame
1157 lwz r2,56+16*4+15*8+12(r1)
1158 lwz r0,56+16*4+15*8+16(r1)
1159 mtxer r0
1160 lwz r0,56+16*4+15*8+4(r1)
1161 mtcrf 0xff,r0
1162 mr r1,r3
1163
1164 // Reeintering 68k emulator
1165 li r0,MODE_68K
1166 stw r0,XLM_RUN_MODE
1167
1168 // Set r0 to 0 for 68k emulator
1169 li r0,0
1170
1171 // Execute next 68k opcode
1172 rlwimi r29,r27,3,13,28
1173 lhau r27,2(r24)
1174 mtlr r29
1175 blr
1176
1177
1178 // Save address of EMUL_OP routine for 68k emulator patch
1179 @3 mflr r0
1180 stw r0,XLM_EMUL_OP_PROC
1181
1182 // Save stack pointer for EMUL_RETURN
1183 stw r1,XLM_EMUL_RETURN_STACK
1184
1185 // Preset registers for ROM boot routine
1186 lis r3,0x40b0 // Pointer to ROM boot structure
1187 ori r3,r3,0xd000
1188
1189 // 68k emulator is now active
1190 li r0,MODE_68K
1191 stw r0,XLM_RUN_MODE
1192
1193 // Jump to ROM
1194 bctr
1195 }
1196
1197 void Start680x0(void)
1198 {
1199 // Install interrupt signal handler
1200 sigemptyset(&sigusr1_action.sa_mask);
1201 sigusr1_action.sa_handler = (__signal_func_ptr)(sigusr1_handler);
1202 sigusr1_action.sa_flags = 0;
1203 sigusr1_action.sa_userdata = NULL;
1204 sigaction(SIGUSR1, &sigusr1_action, NULL);
1205
1206 // Install signal stack
1207 set_signal_stack(malloc(SIG_STACK_SIZE), SIG_STACK_SIZE);
1208
1209 // We're now ready to receive signals
1210 ReadyForSignals = true;
1211
1212 D(bug("Jumping to ROM\n"));
1213 jump_to_rom(ROM_BASE + 0x310000);
1214 D(bug("Returned from ROM\n"));
1215
1216 // We're no longer ready to receive signals
1217 ReadyForSignals = false;
1218 }
1219
1220
1221 /*
1222 * Trigger interrupt
1223 */
1224
1225 void TriggerInterrupt(void)
1226 {
1227 if (emul_thread > 0 && ReadyForSignals)
1228 send_signal(emul_thread, SIGUSR1);
1229 }
1230
1231
1232 /*
1233 * Execute 68k subroutine
1234 * r->a[7] and r->sr are unused!
1235 */
1236
1237 static asm void execute_68k(register uint32 addr, register M68kRegisters *r)
1238 {
1239 // Create stack frame
1240 mflr r0
1241 stw r0,8(r1)
1242 stw r4,12(r1)
1243 stwu r1,-(56+19*4+18*8)(r1)
1244
1245 // Save PowerPC registers
1246 stmw r13,56(r1)
1247 #if SAVE_FP_EXEC_68K
1248 stfd f14,56+19*4+0*8(r1)
1249 stfd f15,56+19*4+1*8(r1)
1250 stfd f16,56+19*4+2*8(r1)
1251 stfd f17,56+19*4+3*8(r1)
1252 stfd f18,56+19*4+4*8(r1)
1253 stfd f19,56+19*4+5*8(r1)
1254 stfd f20,56+19*4+6*8(r1)
1255 stfd f21,56+19*4+7*8(r1)
1256 stfd f22,56+19*4+8*8(r1)
1257 stfd f23,56+19*4+9*8(r1)
1258 stfd f24,56+19*4+10*8(r1)
1259 stfd f25,56+19*4+11*8(r1)
1260 stfd f26,56+19*4+12*8(r1)
1261 stfd f27,56+19*4+13*8(r1)
1262 stfd f28,56+19*4+14*8(r1)
1263 stfd f29,56+19*4+15*8(r1)
1264 stfd f30,56+19*4+16*8(r1)
1265 stfd f31,56+19*4+17*8(r1)
1266 #endif
1267
1268 // Set up registers for 68k emulator
1269 lwz r31,XLM_KERNEL_DATA // Pointer to Kernel Data
1270 addi r31,r31,0x1000 // points to Emulator Data
1271 li r0,0
1272 mtcrf 0xff,r0
1273 creqv 11,11,11 // Supervisor mode
1274 lwz r8,M68kRegisters.d[0](r4)
1275 lwz r9,M68kRegisters.d[1](r4)
1276 lwz r10,M68kRegisters.d[2](r4)
1277 lwz r11,M68kRegisters.d[3](r4)
1278 lwz r12,M68kRegisters.d[4](r4)
1279 lwz r13,M68kRegisters.d[5](r4)
1280 lwz r14,M68kRegisters.d[6](r4)
1281 lwz r15,M68kRegisters.d[7](r4)
1282 lwz r16,M68kRegisters.a[0](r4)
1283 lwz r17,M68kRegisters.a[1](r4)
1284 lwz r18,M68kRegisters.a[2](r4)
1285 lwz r19,M68kRegisters.a[3](r4)
1286 lwz r20,M68kRegisters.a[4](r4)
1287 lwz r21,M68kRegisters.a[5](r4)
1288 lwz r22,M68kRegisters.a[6](r4)
1289 li r23,0
1290 mr r24,r3
1291 lwz r25,XLM_68K_R25 // MSB of SR
1292 li r26,0
1293 li r28,0 // VBR
1294 lwz r29,0x74(r31) // Pointer to opcode table
1295 lwz r30,0x78(r31) // Address of emulator
1296
1297 // Reentering 68k emulator
1298 li r0,MODE_68K
1299 stw r0,XLM_RUN_MODE
1300
1301 // Set r0 to 0 for 68k emulator
1302 li r0,0
1303
1304 // Execute 68k opcode
1305 lha r27,0(r24)
1306 rlwimi r29,r27,3,13,28
1307 lhau r27,2(r24)
1308 mtlr r29
1309 blr
1310 }
1311
1312 void Execute68k(uint32 addr, M68kRegisters *r)
1313 {
1314 uint16 proc[4] = {M68K_JSR, addr >> 16, addr & 0xffff, M68K_EXEC_RETURN};
1315 execute_68k((uint32)proc, r);
1316 }
1317
1318
1319 /*
1320 * Execute MacOS 68k trap
1321 * r->a[7] and r->sr are unused!
1322 */
1323
1324 void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
1325 {
1326 uint16 proc[2] = {trap, M68K_EXEC_RETURN};
1327 execute_68k((uint32)proc, r);
1328 }
1329
1330
1331 /*
1332 * USR1 handler
1333 */
1334
1335 static void sigusr1_handler(int sig, void *arg, vregs *r)
1336 {
1337 // Do nothing if interrupts are disabled
1338 if ((*(int32 *)XLM_IRQ_NEST) > 0)
1339 return;
1340
1341 // 68k emulator active? Then trigger 68k interrupt level 1
1342 if (*(uint32 *)XLM_RUN_MODE == MODE_68K) {
1343 *(uint16 *)(kernel_data->v[0x67c >> 2]) = 1;
1344 r->cr |= kernel_data->v[0x674 >> 2];
1345 }
1346 }