ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/emul_op.cpp
Revision: 1.23
Committed: 2008-01-01T09:47:38Z (16 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.22: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * emul_op.cpp - 68k opcodes for ROM patches
3     *
4 gbeauche 1.23 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include <stdio.h>
22    
23     #include "sysdeps.h"
24     #include "main.h"
25     #include "version.h"
26     #include "prefs.h"
27     #include "cpu_emulation.h"
28     #include "xlowmem.h"
29     #include "xpram.h"
30     #include "timer.h"
31     #include "adb.h"
32     #include "sony.h"
33     #include "disk.h"
34     #include "cdrom.h"
35     #include "scsi.h"
36     #include "video.h"
37     #include "audio.h"
38     #include "ether.h"
39     #include "serial.h"
40     #include "clip.h"
41     #include "extfs.h"
42     #include "macos_util.h"
43     #include "rom_patches.h"
44     #include "rsrc_patches.h"
45     #include "name_registry.h"
46     #include "user_strings.h"
47     #include "emul_op.h"
48 gbeauche 1.5 #include "thunks.h"
49 cebix 1.1
50     #define DEBUG 0
51     #include "debug.h"
52    
53    
54     // TVector of MakeExecutable
55 gbeauche 1.15 static uint32 MakeExecutableTvec;
56 cebix 1.1
57    
58     /*
59     * Execute EMUL_OP opcode (called by 68k emulator)
60     */
61    
62     void EmulOp(M68kRegisters *r, uint32 pc, int selector)
63     {
64     D(bug("EmulOp %04x at %08x\n", selector, pc));
65     switch (selector) {
66     case OP_BREAK: // Breakpoint
67     printf("*** Breakpoint\n");
68     Dump68kRegs(r);
69     break;
70    
71     case OP_XPRAM1: { // Read/write from/to XPRam
72     uint32 len = r->d[3];
73     uint8 *adr = Mac2HostAddr(r->a[3]);
74     D(bug("XPRAMReadWrite d3: %08lx, a3: %p\n", len, adr));
75     int ofs = len & 0xffff;
76     len >>= 16;
77     if (len & 0x8000) {
78     len &= 0x7fff;
79     for (uint32 i=0; i<len; i++)
80     XPRAM[((ofs + i) & 0xff) + 0x1300] = *adr++;
81     } else {
82     for (uint32 i=0; i<len; i++)
83     *adr++ = XPRAM[((ofs + i) & 0xff) + 0x1300];
84     }
85     break;
86     }
87    
88     case OP_XPRAM2: // Read from XPRam
89     r->d[1] = XPRAM[(r->d[1] & 0xff) + 0x1300];
90     break;
91    
92     case OP_XPRAM3: // Write to XPRam
93     XPRAM[(r->d[1] & 0xff) + 0x1300] = r->d[2];
94     break;
95    
96     case OP_NVRAM1: { // Read from NVRAM
97     int ofs = r->d[0];
98     r->d[0] = XPRAM[ofs & 0x1fff];
99     bool localtalk = !(XPRAM[0x13e0] || XPRAM[0x13e1]); // LocalTalk enabled?
100     switch (ofs) {
101     case 0x13e0: // Disable LocalTalk (use EtherTalk instead)
102     if (localtalk)
103     r->d[0] = 0x00;
104     break;
105     case 0x13e1:
106     if (localtalk)
107     r->d[0] = 0x01;
108     break;
109     case 0x13e2:
110     if (localtalk)
111     r->d[0] = 0x00;
112     break;
113     case 0x13e3:
114     if (localtalk)
115     r->d[0] = 0x0a;
116     break;
117     }
118     break;
119     }
120    
121     case OP_NVRAM2: // Write to NVRAM
122     XPRAM[r->d[0] & 0x1fff] = r->d[1];
123     break;
124    
125     case OP_NVRAM3: // Read/write from/to NVRAM
126     if (r->d[3]) {
127     r->d[0] = XPRAM[(r->d[4] + 0x1300) & 0x1fff];
128     } else {
129     XPRAM[(r->d[4] + 0x1300) & 0x1fff] = r->d[5];
130     r->d[0] = 0;
131     }
132     break;
133    
134     case OP_FIX_MEMTOP: // Fixes MemTop in BootGlobs during startup
135     D(bug("Fix MemTop\n"));
136     WriteMacInt32(BootGlobsAddr - 20, RAMBase + RAMSize); // MemTop
137     r->a[6] = RAMBase + RAMSize;
138     break;
139    
140     case OP_FIX_MEMSIZE: { // Fixes physical/logical RAM size during startup
141     D(bug("Fix MemSize\n"));
142     uint32 diff = ReadMacInt32(0x1ef8) - ReadMacInt32(0x1ef4);
143     WriteMacInt32(0x1ef8, RAMSize); // Physical RAM size
144     WriteMacInt32(0x1ef4, RAMSize - diff); // Logical RAM size
145     break;
146     }
147    
148     case OP_FIX_BOOTSTACK: // Fixes boot stack pointer in boot 3 resource
149     D(bug("Fix BootStack\n"));
150     r->a[1] = r->a[7] = RAMBase + RAMSize * 3 / 4;
151     break;
152    
153     case OP_SONY_OPEN: // Floppy driver functions
154     r->d[0] = SonyOpen(r->a[0], r->a[1]);
155     break;
156     case OP_SONY_PRIME:
157     r->d[0] = SonyPrime(r->a[0], r->a[1]);
158     break;
159     case OP_SONY_CONTROL:
160     r->d[0] = SonyControl(r->a[0], r->a[1]);
161     break;
162     case OP_SONY_STATUS:
163     r->d[0] = SonyStatus(r->a[0], r->a[1]);
164     break;
165    
166     case OP_DISK_OPEN: // Disk driver functions
167     r->d[0] = DiskOpen(r->a[0], r->a[1]);
168     break;
169     case OP_DISK_PRIME:
170     r->d[0] = DiskPrime(r->a[0], r->a[1]);
171     break;
172     case OP_DISK_CONTROL:
173     r->d[0] = DiskControl(r->a[0], r->a[1]);
174     break;
175     case OP_DISK_STATUS:
176     r->d[0] = DiskStatus(r->a[0], r->a[1]);
177     break;
178    
179     case OP_CDROM_OPEN: // CD-ROM driver functions
180     r->d[0] = CDROMOpen(r->a[0], r->a[1]);
181     break;
182     case OP_CDROM_PRIME:
183     r->d[0] = CDROMPrime(r->a[0], r->a[1]);
184     break;
185     case OP_CDROM_CONTROL:
186     r->d[0] = CDROMControl(r->a[0], r->a[1]);
187     break;
188     case OP_CDROM_STATUS:
189     r->d[0] = CDROMStatus(r->a[0], r->a[1]);
190     break;
191    
192     case OP_AUDIO_DISPATCH: // Audio component functions
193     r->d[0] = AudioDispatch(r->a[3], r->a[4]);
194     break;
195    
196     case OP_SOUNDIN_OPEN: // Sound input driver functions
197     r->d[0] = SoundInOpen(r->a[0], r->a[1]);
198     break;
199     case OP_SOUNDIN_PRIME:
200     r->d[0] = SoundInPrime(r->a[0], r->a[1]);
201     break;
202     case OP_SOUNDIN_CONTROL:
203     r->d[0] = SoundInControl(r->a[0], r->a[1]);
204     break;
205     case OP_SOUNDIN_STATUS:
206     r->d[0] = SoundInStatus(r->a[0], r->a[1]);
207     break;
208     case OP_SOUNDIN_CLOSE:
209     r->d[0] = SoundInClose(r->a[0], r->a[1]);
210     break;
211    
212     case OP_ADBOP: // ADBOp() replacement
213     ADBOp(r->d[0], Mac2HostAddr(ReadMacInt32(r->a[0])));
214     break;
215    
216     case OP_INSTIME: // InsTime() replacement
217     r->d[0] = InsTime(r->a[0], r->d[1]);
218     break;
219     case OP_RMVTIME: // RmvTime() replacement
220     r->d[0] = RmvTime(r->a[0]);
221     break;
222     case OP_PRIMETIME: // PrimeTime() replacement
223     r->d[0] = PrimeTime(r->a[0], r->d[0]);
224     break;
225    
226     case OP_MICROSECONDS: // Microseconds() replacement
227     Microseconds(r->a[0], r->d[0]);
228     break;
229    
230     case OP_PUT_SCRAP: // PutScrap() patch
231     PutScrap(ReadMacInt32(r->a[7] + 8), Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 12));
232     break;
233    
234     case OP_GET_SCRAP: // GetScrap() patch
235     GetScrap((void **)Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 12));
236     break;
237    
238     case OP_DEBUG_STR: // DebugStr() shows warning message
239     if (PrefsFindBool("nogui")) {
240     uint8 *pstr = Mac2HostAddr(ReadMacInt32(r->a[7] + 4));
241     char str[256];
242     int i;
243     for (i=0; i<pstr[0]; i++)
244     str[i] = pstr[i+1];
245     str[i] = 0;
246     WarningAlert(str);
247     }
248     break;
249    
250     case OP_INSTALL_DRIVERS: { // Patch to install our own drivers during startup
251     // Install drivers
252     InstallDrivers();
253    
254     // Patch MakeExecutable()
255 gbeauche 1.17 MakeExecutableTvec = FindLibSymbol("\023PrivateInterfaceLib", "\016MakeExecutable");
256 gbeauche 1.15 D(bug("MakeExecutable TVECT at %08x\n", MakeExecutableTvec));
257     WriteMacInt32(MakeExecutableTvec, NativeFunction(NATIVE_MAKE_EXECUTABLE));
258 gbeauche 1.5 #if !EMULATED_PPC
259 gbeauche 1.15 WriteMacInt32(MakeExecutableTvec + 4, (uint32)TOC);
260 cebix 1.1 #endif
261    
262     // Patch DebugStr()
263 gbeauche 1.16 static const uint8 proc_template[] = {
264     M68K_EMUL_OP_DEBUG_STR >> 8, M68K_EMUL_OP_DEBUG_STR,
265     0x4e, 0x74, // rtd #4
266     0x00, 0x04
267 cebix 1.1 };
268 gbeauche 1.16 BUILD_SHEEPSHAVER_PROCEDURE(proc);
269     WriteMacInt32(0x1dfc, proc);
270 cebix 1.1 break;
271     }
272    
273     case OP_NAME_REGISTRY: // Patch Name Registry and initialize CallUniversalProc
274     r->d[0] = (uint32)-1;
275     PatchNameRegistry();
276     InitCallUniversalProc();
277     break;
278    
279     case OP_RESET: // Early in MacOS reset
280     D(bug("*** RESET ***\n"));
281     TimerReset();
282     MacOSUtilReset();
283     AudioReset();
284 gbeauche 1.13
285 gbeauche 1.20 // Enable DR emulator (disabled for now)
286     if (PrefsFindBool("jit68k") && 0) {
287 gbeauche 1.13 D(bug("DR activated\n"));
288     WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation
289     WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE);
290     WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE);
291     WriteMacInt32(KernelDataAddr + 0x1b04, DR_CACHE_BASE);
292     WriteMacInt32(KernelDataAddr + 0x1b00, DR_EMULATOR_BASE);
293     memcpy((void *)DR_EMULATOR_BASE, (void *)(ROM_BASE + 0x370000), DR_EMULATOR_SIZE);
294 gbeauche 1.15 MakeExecutable(0, DR_EMULATOR_BASE, DR_EMULATOR_SIZE);
295 gbeauche 1.13 }
296 cebix 1.1 break;
297    
298     case OP_IRQ: // Level 1 interrupt
299     WriteMacInt16(ReadMacInt32(KernelDataAddr + 0x67c), 0); // Clear interrupt
300     r->d[0] = 0;
301     if (HasMacStarted()) {
302     if (InterruptFlags & INTFLAG_VIA) {
303     ClearInterruptFlag(INTFLAG_VIA);
304     #if !PRECISE_TIMING
305     TimerInterrupt();
306     #endif
307 gbeauche 1.2 ExecuteNative(NATIVE_VIDEO_VBL);
308 cebix 1.1
309     static int tick_counter = 0;
310     if (++tick_counter >= 60) {
311     tick_counter = 0;
312     SonyInterrupt();
313     DiskInterrupt();
314     CDROMInterrupt();
315     }
316    
317     r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc.
318     }
319     if (InterruptFlags & INTFLAG_SERIAL) {
320     ClearInterruptFlag(INTFLAG_SERIAL);
321     SerialInterrupt();
322     }
323     if (InterruptFlags & INTFLAG_ETHER) {
324     ClearInterruptFlag(INTFLAG_ETHER);
325 gbeauche 1.2 ExecuteNative(NATIVE_ETHER_IRQ);
326 cebix 1.1 }
327     if (InterruptFlags & INTFLAG_TIMER) {
328     ClearInterruptFlag(INTFLAG_TIMER);
329     TimerInterrupt();
330     }
331     if (InterruptFlags & INTFLAG_AUDIO) {
332     ClearInterruptFlag(INTFLAG_AUDIO);
333     AudioInterrupt();
334     }
335     if (InterruptFlags & INTFLAG_ADB) {
336     ClearInterruptFlag(INTFLAG_ADB);
337     ADBInterrupt();
338     }
339     } else
340     r->d[0] = 1;
341     break;
342    
343     case OP_SCSI_DISPATCH: { // SCSIDispatch() replacement
344     uint32 ret = ReadMacInt32(r->a[7]);
345     uint16 sel = ReadMacInt16(r->a[7] + 4);
346     r->a[7] += 6;
347     // D(bug("SCSIDispatch(%d)\n", sel));
348     int stack;
349     switch (sel) {
350     case 0: // SCSIReset
351     WriteMacInt16(r->a[7], SCSIReset());
352     stack = 0;
353     break;
354     case 1: // SCSIGet
355     WriteMacInt16(r->a[7], SCSIGet());
356     stack = 0;
357     break;
358     case 2: // SCSISelect
359     case 11: // SCSISelAtn
360     WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt8(r->a[7] + 1)));
361     stack = 2;
362     break;
363     case 3: // SCSICmd
364     WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2))));
365     stack = 6;
366     break;
367     case 4: // SCSIComplete
368     WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8)));
369     stack = 12;
370     break;
371     case 5: // SCSIRead
372     case 8: // SCSIRBlind
373     WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7])));
374     stack = 4;
375     break;
376     case 6: // SCSIWrite
377     case 9: // SCSIWBlind
378     WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7])));
379     stack = 4;
380     break;
381     case 10: // SCSIStat
382     WriteMacInt16(r->a[7], SCSIStat());
383     stack = 0;
384     break;
385     case 12: // SCSIMsgIn
386     WriteMacInt16(r->a[7] + 4, 0);
387     stack = 4;
388     break;
389     case 13: // SCSIMsgOut
390     WriteMacInt16(r->a[7] + 2, 0);
391     stack = 2;
392     break;
393     case 14: // SCSIMgrBusy
394     WriteMacInt16(r->a[7], SCSIMgrBusy());
395     stack = 0;
396     break;
397     default:
398     printf("FATAL: SCSIDispatch: illegal selector\n");
399     stack = 0;
400     //!! SysError(12)
401     }
402     r->a[0] = ret;
403     r->a[7] += stack;
404     break;
405     }
406    
407     case OP_SCSI_ATOMIC: // SCSIAtomic() replacement
408     D(bug("SCSIAtomic\n"));
409     r->d[0] = (uint32)-7887;
410     break;
411    
412 gbeauche 1.22 case OP_CHECK_SYSV: { // Check we are not using MacOS < 8.1 with a NewWorld ROM
413     r->a[1] = r->d[1];
414     r->a[0] = ReadMacInt32(r->d[1]);
415     uint32 sysv = ReadMacInt16(r->a[0]);
416     D(bug("Detected MacOS version %d.%d.%d\n", (sysv >> 8) & 0xf, (sysv >> 4) & 0xf, sysv & 0xf));
417     if (ROMType == ROMTYPE_NEWWORLD && sysv < 0x0801)
418     r->d[1] = 0;
419     break;
420     }
421    
422 cebix 1.1 case OP_NTRB_17_PATCH:
423     r->a[2] = ReadMacInt32(r->a[7]);
424     r->a[7] += 4;
425     if (ReadMacInt16(r->a[2] + 6) == 17)
426     PatchNativeResourceManager();
427     break;
428    
429     case OP_NTRB_17_PATCH2:
430     r->a[7] += 8;
431     PatchNativeResourceManager();
432     break;
433    
434     case OP_NTRB_17_PATCH3:
435     r->a[2] = ReadMacInt32(r->a[7]);
436     r->a[7] += 4;
437     D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
438     if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
439     PatchNativeResourceManager();
440     break;
441    
442 gbeauche 1.14 case OP_NTRB_17_PATCH4:
443     r->d[0] = ReadMacInt16(r->a[7]);
444     r->a[7] += 2;
445     D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
446     if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
447     PatchNativeResourceManager();
448     break;
449    
450 cebix 1.1 case OP_CHECKLOAD: { // vCheckLoad() patch
451     uint32 type = ReadMacInt32(r->a[7]);
452     r->a[7] += 4;
453     int16 id = ReadMacInt16(r->a[2]);
454     if (r->a[0] == 0)
455     break;
456     uint32 adr = ReadMacInt32(r->a[0]);
457     if (adr == 0)
458     break;
459     uint16 *p = (uint16 *)Mac2HostAddr(adr);
460     uint32 size = ReadMacInt32(adr - 8) & 0xffffff;
461     CheckLoad(type, id, p, size);
462     break;
463     }
464    
465     case OP_EXTFS_COMM: // External file system routines
466     WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4)));
467     break;
468    
469     case OP_EXTFS_HFS:
470     WriteMacInt16(r->a[7] + 20, ExtFSHFS(ReadMacInt32(r->a[7] + 16), ReadMacInt16(r->a[7] + 14), ReadMacInt32(r->a[7] + 10), ReadMacInt32(r->a[7] + 6), ReadMacInt16(r->a[7] + 4)));
471     break;
472    
473     case OP_IDLE_TIME:
474     // Sleep if no events pending
475 gbeauche 1.9 if (ReadMacInt32(0x14c) == 0)
476 gbeauche 1.21 idle_wait();
477 cebix 1.1 r->a[0] = ReadMacInt32(0x2b6);
478     break;
479    
480 gbeauche 1.9 case OP_IDLE_TIME_2:
481     // Sleep if no events pending
482     if (ReadMacInt32(0x14c) == 0)
483 gbeauche 1.21 idle_wait();
484 gbeauche 1.9 r->d[0] = (uint32)-2;
485     break;
486    
487 cebix 1.1 default:
488     printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector);
489     QuitEmulator();
490     break;
491     }
492     }