ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/emul_op.cpp
Revision: 1.2
Committed: 2003-09-07T14:33:51Z (20 years, 8 months ago) by gbeauche
Branch: MAIN
Changes since 1.1: +12 -5 lines
Log Message:
- Integrate new NativeOp instructions to be used as trampolines to call
  native functions from ppc code.
- Little endian fixes in emul_op.cpp
- Add new 'gpch' 750 patch to workaround crash with MacOS 8.6
- Don't crash in Process Manager on reset/shutdown with MacOS 8.6
- We also have an experimental interrupt thread in emulation mode

File Contents

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