ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp
Revision: 1.1
Committed: 1999-10-03T14:16:26Z (25 years, 2 months ago) by cebix
Branch: MAIN
Branch point for: cebix
Log Message:
Initial revision

File Contents

# User Rev Content
1 cebix 1.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     }