ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/emul_op.cpp
Revision: 1.11
Committed: 2004-05-31T10:02:20Z (19 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.10: +2 -2 lines
Log Message:
Enable DR emulator with OldWorld ROMs too. It turned out that translated
code was also trying to access Serial memory.

Note however that I noticed some rare crashes with the DR emulator.
Probably caused by nested runs from EmulOps? We'd really want a native
68k emulator too for Execute68k() things.

File Contents

# Content
1 /*
2 * emul_op.cpp - 68k opcodes for ROM patches
3 *
4 * SheepShaver (C) 1997-2004 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 #include "thunks.h"
49
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 static uint32 *MakeExecutableTvec;
63
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 MakeExecutableTvec = (uint32 *)FindLibSymbol("\023PrivateInterfaceLib", "\016MakeExecutable");
263 D(bug("MakeExecutable TVECT at %p\n", MakeExecutableTvec));
264 MakeExecutableTvec[0] = htonl(NativeFunction(NATIVE_MAKE_EXECUTABLE));
265 #if !EMULATED_PPC
266 MakeExecutableTvec[1] = (uint32)TOC;
267 #endif
268
269 // Patch DebugStr()
270 static const uint16 proc[] = {
271 PW(M68K_EMUL_OP_DEBUG_STR),
272 PW(0x4e74), // rtd #4
273 PW(0x0004)
274 };
275 WriteMacInt32(0x1dfc, (uint32)proc);
276 break;
277 }
278
279 case OP_NAME_REGISTRY: // Patch Name Registry and initialize CallUniversalProc
280 r->d[0] = (uint32)-1;
281 PatchNameRegistry();
282 InitCallUniversalProc();
283 break;
284
285 case OP_RESET: // Early in MacOS reset
286 D(bug("*** RESET ***\n"));
287 TimerReset();
288 MacOSUtilReset();
289 AudioReset();
290
291 // Enable DR emulator
292 if (1) {
293 D(bug("DR activated\n"));
294 WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation
295 WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE);
296 WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE);
297 WriteMacInt32(KernelDataAddr + 0x1b04, DR_CACHE_BASE);
298 WriteMacInt32(KernelDataAddr + 0x1b00, DR_EMULATOR_BASE);
299 memcpy((void *)DR_EMULATOR_BASE, (void *)(ROM_BASE + 0x370000), DR_EMULATOR_SIZE);
300 MakeExecutable(0, (void *)DR_EMULATOR_BASE, DR_EMULATOR_SIZE);
301 }
302 break;
303
304 case OP_IRQ: // Level 1 interrupt
305 WriteMacInt16(ReadMacInt32(KernelDataAddr + 0x67c), 0); // Clear interrupt
306 r->d[0] = 0;
307 if (HasMacStarted()) {
308 if (InterruptFlags & INTFLAG_VIA) {
309 ClearInterruptFlag(INTFLAG_VIA);
310 #if !PRECISE_TIMING
311 TimerInterrupt();
312 #endif
313 ExecuteNative(NATIVE_VIDEO_VBL);
314
315 static int tick_counter = 0;
316 if (++tick_counter >= 60) {
317 tick_counter = 0;
318 SonyInterrupt();
319 DiskInterrupt();
320 CDROMInterrupt();
321 }
322
323 r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc.
324 }
325 if (InterruptFlags & INTFLAG_SERIAL) {
326 ClearInterruptFlag(INTFLAG_SERIAL);
327 SerialInterrupt();
328 }
329 if (InterruptFlags & INTFLAG_ETHER) {
330 ClearInterruptFlag(INTFLAG_ETHER);
331 ExecuteNative(NATIVE_ETHER_IRQ);
332 }
333 if (InterruptFlags & INTFLAG_TIMER) {
334 ClearInterruptFlag(INTFLAG_TIMER);
335 TimerInterrupt();
336 }
337 if (InterruptFlags & INTFLAG_AUDIO) {
338 ClearInterruptFlag(INTFLAG_AUDIO);
339 AudioInterrupt();
340 }
341 if (InterruptFlags & INTFLAG_ADB) {
342 ClearInterruptFlag(INTFLAG_ADB);
343 ADBInterrupt();
344 }
345 } else
346 r->d[0] = 1;
347 break;
348
349 case OP_SCSI_DISPATCH: { // SCSIDispatch() replacement
350 uint32 ret = ReadMacInt32(r->a[7]);
351 uint16 sel = ReadMacInt16(r->a[7] + 4);
352 r->a[7] += 6;
353 // D(bug("SCSIDispatch(%d)\n", sel));
354 int stack;
355 switch (sel) {
356 case 0: // SCSIReset
357 WriteMacInt16(r->a[7], SCSIReset());
358 stack = 0;
359 break;
360 case 1: // SCSIGet
361 WriteMacInt16(r->a[7], SCSIGet());
362 stack = 0;
363 break;
364 case 2: // SCSISelect
365 case 11: // SCSISelAtn
366 WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt8(r->a[7] + 1)));
367 stack = 2;
368 break;
369 case 3: // SCSICmd
370 WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2))));
371 stack = 6;
372 break;
373 case 4: // SCSIComplete
374 WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8)));
375 stack = 12;
376 break;
377 case 5: // SCSIRead
378 case 8: // SCSIRBlind
379 WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7])));
380 stack = 4;
381 break;
382 case 6: // SCSIWrite
383 case 9: // SCSIWBlind
384 WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7])));
385 stack = 4;
386 break;
387 case 10: // SCSIStat
388 WriteMacInt16(r->a[7], SCSIStat());
389 stack = 0;
390 break;
391 case 12: // SCSIMsgIn
392 WriteMacInt16(r->a[7] + 4, 0);
393 stack = 4;
394 break;
395 case 13: // SCSIMsgOut
396 WriteMacInt16(r->a[7] + 2, 0);
397 stack = 2;
398 break;
399 case 14: // SCSIMgrBusy
400 WriteMacInt16(r->a[7], SCSIMgrBusy());
401 stack = 0;
402 break;
403 default:
404 printf("FATAL: SCSIDispatch: illegal selector\n");
405 stack = 0;
406 //!! SysError(12)
407 }
408 r->a[0] = ret;
409 r->a[7] += stack;
410 break;
411 }
412
413 case OP_SCSI_ATOMIC: // SCSIAtomic() replacement
414 D(bug("SCSIAtomic\n"));
415 r->d[0] = (uint32)-7887;
416 break;
417
418 case OP_NTRB_17_PATCH:
419 r->a[2] = ReadMacInt32(r->a[7]);
420 r->a[7] += 4;
421 if (ReadMacInt16(r->a[2] + 6) == 17)
422 PatchNativeResourceManager();
423 break;
424
425 case OP_NTRB_17_PATCH2:
426 r->a[7] += 8;
427 PatchNativeResourceManager();
428 break;
429
430 case OP_NTRB_17_PATCH3:
431 r->a[2] = ReadMacInt32(r->a[7]);
432 r->a[7] += 4;
433 D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
434 if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
435 PatchNativeResourceManager();
436 break;
437
438 case OP_CHECKLOAD: { // vCheckLoad() patch
439 uint32 type = ReadMacInt32(r->a[7]);
440 r->a[7] += 4;
441 int16 id = ReadMacInt16(r->a[2]);
442 if (r->a[0] == 0)
443 break;
444 uint32 adr = ReadMacInt32(r->a[0]);
445 if (adr == 0)
446 break;
447 uint16 *p = (uint16 *)Mac2HostAddr(adr);
448 uint32 size = ReadMacInt32(adr - 8) & 0xffffff;
449 CheckLoad(type, id, p, size);
450 break;
451 }
452
453 case OP_EXTFS_COMM: // External file system routines
454 WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4)));
455 break;
456
457 case OP_EXTFS_HFS:
458 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)));
459 break;
460
461 case OP_IDLE_TIME:
462 // Sleep if no events pending
463 if (ReadMacInt32(0x14c) == 0)
464 Delay_usec(16667);
465 r->a[0] = ReadMacInt32(0x2b6);
466 break;
467
468 case OP_IDLE_TIME_2:
469 // Sleep if no events pending
470 if (ReadMacInt32(0x14c) == 0)
471 Delay_usec(16667);
472 r->d[0] = (uint32)-2;
473 break;
474
475 default:
476 printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector);
477 QuitEmulator();
478 break;
479 }
480 }