ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/emul_op.cpp
Revision: 1.19
Committed: 2005-03-05T19:07:35Z (19 years, 8 months ago) by gbeauche
Branch: MAIN
Changes since 1.18: +0 -7 lines
Log Message:
Enable high precision timings on POSIX systems supporting clock_nanosleep().
Since pthread_suspend_np() is not available to Linux (but NetBSD 2.0), thread
suspend is implemented likewise to boehm-gc.

File Contents

# Content
1 /*
2 * emul_op.cpp - 68k opcodes for ROM patches
3 *
4 * SheepShaver (C) 1997-2005 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 // TVector of MakeExecutable
55 static uint32 MakeExecutableTvec;
56
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 MakeExecutableTvec = FindLibSymbol("\023PrivateInterfaceLib", "\016MakeExecutable");
256 D(bug("MakeExecutable TVECT at %08x\n", MakeExecutableTvec));
257 WriteMacInt32(MakeExecutableTvec, NativeFunction(NATIVE_MAKE_EXECUTABLE));
258 #if !EMULATED_PPC
259 WriteMacInt32(MakeExecutableTvec + 4, (uint32)TOC);
260 #endif
261
262 // Patch DebugStr()
263 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 };
268 BUILD_SHEEPSHAVER_PROCEDURE(proc);
269 WriteMacInt32(0x1dfc, proc);
270 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
285 // Enable DR emulator
286 if (PrefsFindBool("jit68k")) {
287 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 MakeExecutable(0, DR_EMULATOR_BASE, DR_EMULATOR_SIZE);
295 }
296 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 ExecuteNative(NATIVE_VIDEO_VBL);
308
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 ExecuteNative(NATIVE_ETHER_IRQ);
326 }
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 case OP_NTRB_17_PATCH:
413 r->a[2] = ReadMacInt32(r->a[7]);
414 r->a[7] += 4;
415 if (ReadMacInt16(r->a[2] + 6) == 17)
416 PatchNativeResourceManager();
417 break;
418
419 case OP_NTRB_17_PATCH2:
420 r->a[7] += 8;
421 PatchNativeResourceManager();
422 break;
423
424 case OP_NTRB_17_PATCH3:
425 r->a[2] = ReadMacInt32(r->a[7]);
426 r->a[7] += 4;
427 D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
428 if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
429 PatchNativeResourceManager();
430 break;
431
432 case OP_NTRB_17_PATCH4:
433 r->d[0] = ReadMacInt16(r->a[7]);
434 r->a[7] += 2;
435 D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
436 if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
437 PatchNativeResourceManager();
438 break;
439
440 case OP_CHECKLOAD: { // vCheckLoad() patch
441 uint32 type = ReadMacInt32(r->a[7]);
442 r->a[7] += 4;
443 int16 id = ReadMacInt16(r->a[2]);
444 if (r->a[0] == 0)
445 break;
446 uint32 adr = ReadMacInt32(r->a[0]);
447 if (adr == 0)
448 break;
449 uint16 *p = (uint16 *)Mac2HostAddr(adr);
450 uint32 size = ReadMacInt32(adr - 8) & 0xffffff;
451 CheckLoad(type, id, p, size);
452 break;
453 }
454
455 case OP_EXTFS_COMM: // External file system routines
456 WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4)));
457 break;
458
459 case OP_EXTFS_HFS:
460 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)));
461 break;
462
463 case OP_IDLE_TIME:
464 // Sleep if no events pending
465 if (ReadMacInt32(0x14c) == 0)
466 Delay_usec(16667);
467 r->a[0] = ReadMacInt32(0x2b6);
468 break;
469
470 case OP_IDLE_TIME_2:
471 // Sleep if no events pending
472 if (ReadMacInt32(0x14c) == 0)
473 Delay_usec(16667);
474 r->d[0] = (uint32)-2;
475 break;
476
477 default:
478 printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector);
479 QuitEmulator();
480 break;
481 }
482 }