ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/emul_op.cpp
Revision: 1.18
Committed: 2005-01-30T21:48:19Z (19 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.17: +1 -1 lines
Log Message:
Happy New Year 2005!

File Contents

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