ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/emul_op.cpp
Revision: 1.4
Committed: 2003-10-26T08:48:48Z (20 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.3: +1 -1 lines
Log Message:
fix MakeExecutable patch for little endian systems

File Contents

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