ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/powerrom_cpu/powerrom_cpu.cpp
Revision: 1.10
Committed: 2006-04-30T21:26:21Z (18 years, 7 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-19
Changes since 1.9: +2 -0 lines
Log Message:
Tentative fixes to BeOS idle suspend/resume routines. Well, I have no-op'ed
them. So, if someone has BeOS and wants to give it a try, please change and
test this new code. Corner case could be a resume_thread() when emul_thread
is not suspended.

Fixlet to powerrom_cpu: call idle_resume() from TriggerInterrupt().

File Contents

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