ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/emul_ppc/emul_ppc.cpp
Revision: 1.5
Committed: 2009-08-18T18:26:11Z (15 years, 3 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +1 -1 lines
Log Message:
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.


Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".

SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.

The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.

On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.


Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.

This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.

Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.

A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.


Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.

The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.

This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.


Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.

2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.

3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.

4. Changed and rearranged the allocation of RAM and ROM areas.

Before it worked like this:

  - Allocate ROM area
  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0, allocate at fixed address

We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:

  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0
      if REAL addressing
         allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
      else (direct addressing)
         allocate RAM at fixed address
  - If ROM hasn't been allocated yet, allocate at fixed address

5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.

6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.

7. Change subsequent code from using constant ROM_BASE to variable ROMBase.


Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.

ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.

ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.

main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.

cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.

user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.

File Contents

# Content
1 /*
2 * emul_ppc.cpp - PowerPC processor emulation
3 *
4 * SheepShaver (C) 1997-2008 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 /*
22 TODO:
23 addme
24 addmeo
25 addze
26 addzeo
27 dcbst
28 dcbt
29 dcbtst
30 divwuo
31 fabs
32 fadd
33 fadds
34 fcmpo
35 fcmpu
36 fctiw
37 fctiwz
38 fdiv
39 fdivs
40 fmadd
41 fmadds
42 fmr
43 fmsub
44 fmsubs
45 fmul
46 fmuls
47 fnabs
48 fneg
49 fnmadd
50 fnmadds
51 fnmsub
52 fnmsubs
53 fres
54 frsp
55 frsqrte
56 fsel
57 fsqrt
58 fsqrts
59 fsub
60 fsubs
61 lfdu
62 lfdux
63 lfdx
64 lfs
65 lfsu
66 lfsux
67 lfsx
68 lhbrx
69 lwbrx
70 mcrfs
71 mcrxr
72 mtfsb0
73 mtfsb1
74 mtfsfi
75 mulhwu
76 mullwo
77 nego
78 sc
79 stfdu
80 stfdux
81 stfdx
82 stfs
83 stfsu
84 stfsux
85 stfsx
86 sthbrx
87 stwbrx
88 subfo
89 subfme
90 subfmeo
91 subfze
92 subfzeo
93 tw
94 twi
95
96 CHECK:
97 crxor
98 creqv
99 */
100
101 #include <stdio.h>
102 #include <signal.h>
103
104 #include "sysdeps.h"
105 #include "cpu_emulation.h"
106 #include "main.h"
107 #include "xlowmem.h"
108 #include "emul_op.h"
109
110 #if ENABLE_MON
111 #include "mon.h"
112 #include "mon_disass.h"
113 #endif
114
115 #define DEBUG 1
116 #include "debug.h"
117
118 #define FLIGHT_RECORDER 1
119
120
121 // PowerPC user mode registers
122 uint32 r[32];
123 double fr[32];
124 uint32 lr, ctr;
125 uint32 cr, xer;
126 uint32 fpscr;
127 uint32 pc;
128
129 // Convert 8-bit field mask (e.g. mtcrf) to bit mask
130 static uint32 field2mask[256];
131
132
133 /*
134 * Flight recorder
135 */
136
137 #if FLIGHT_RECORDER
138 struct rec_step {
139 uint32 r[32];
140 double fr[32];
141 uint32 lr, ctr;
142 uint32 cr, xer;
143 uint32 fpscr;
144 uint32 pc;
145 uint32 opcode;
146 };
147
148 const int LOG_SIZE = 8192;
149 static rec_step log[LOG_SIZE];
150 static int log_ptr = 0;
151
152 static void record_step(uint32 opcode)
153 {
154 for (int i=0; i<32; i++) {
155 log[log_ptr].r[i] = r[i];
156 log[log_ptr].fr[i] = fr[i];
157 }
158 log[log_ptr].lr = lr;
159 log[log_ptr].ctr = ctr;
160 log[log_ptr].cr = cr;
161 log[log_ptr].xer = xer;
162 log[log_ptr].fpscr = fpscr;
163 log[log_ptr].pc = pc;
164 log[log_ptr].opcode = opcode;
165 log_ptr++;
166 if (log_ptr == LOG_SIZE)
167 log_ptr = 0;
168 }
169
170 static void dump_log(void)
171 {
172 FILE *f = fopen("log", "w");
173 if (f == NULL)
174 return;
175 for (int i=0; i<LOG_SIZE; i++) {
176 int j = (i + log_ptr) % LOG_SIZE;
177 fprintf(f, "pc %08x lr %08x ctr %08x cr %08x xer %08x ", log[j].pc, log[j].lr, log[j].ctr, log[j].cr, log[j].xer);
178 fprintf(f, "r0 %08x r1 %08x r2 %08x r3 %08x ", log[j].r[0], log[j].r[1], log[j].r[2], log[j].r[3]);
179 fprintf(f, "r4 %08x r5 %08x r6 %08x r7 %08x ", log[j].r[4], log[j].r[5], log[j].r[6], log[j].r[7]);
180 fprintf(f, "r8 %08x r9 %08x r10 %08x r11 %08x ", log[j].r[8], log[j].r[9], log[j].r[10], log[j].r[11]);
181 fprintf(f, "r12 %08x r13 %08x r14 %08x r15 %08x ", log[j].r[12], log[j].r[13], log[j].r[14], log[j].r[15]);
182 fprintf(f, "r16 %08x r17 %08x r18 %08x r19 %08x ", log[j].r[16], log[j].r[17], log[j].r[18], log[j].r[19]);
183 fprintf(f, "r20 %08x r21 %08x r22 %08x r23 %08x ", log[j].r[20], log[j].r[21], log[j].r[22], log[j].r[23]);
184 fprintf(f, "r24 %08x r25 %08x r26 %08x r27 %08x ", log[j].r[24], log[j].r[25], log[j].r[26], log[j].r[27]);
185 fprintf(f, "r28 %08x r29 %08x r30 %08x r31 %08x\n", log[j].r[28], log[j].r[29], log[j].r[30], log[j].r[31]);
186 #if ENABLE_MON
187 disass_ppc(f, log[j].pc, log[j].opcode);
188 #endif
189 }
190 fclose(f);
191 }
192 #endif
193
194
195 /*
196 * Dump PPC registers
197 */
198
199 static void dump(void)
200 {
201 // Dump registers
202 printf(" r0 %08x r1 %08x r2 %08x r3 %08x\n", r[0], r[1], r[2], r[3]);
203 printf(" r4 %08x r5 %08x r6 %08x r7 %08x\n", r[4], r[5], r[6], r[7]);
204 printf(" r8 %08x r9 %08x r10 %08x r11 %08x\n", r[8], r[9], r[10], r[11]);
205 printf("r12 %08x r13 %08x r14 %08x r15 %08x\n", r[12], r[13], r[14], r[15]);
206 printf("r16 %08x r17 %08x r18 %08x r19 %08x\n", r[16], r[17], r[18], r[19]);
207 printf("r20 %08x r21 %08x r22 %08x r23 %08x\n", r[20], r[21], r[22], r[23]);
208 printf("r24 %08x r25 %08x r26 %08x r27 %08x\n", r[24], r[25], r[26], r[27]);
209 printf("r28 %08x r29 %08x r30 %08x r31 %08x\n", r[28], r[29], r[30], r[31]);
210 printf(" lr %08x ctr %08x cr %08x xer %08x\n", lr, ctr, cr, xer);
211 printf(" pc %08x fpscr %08x\n", pc, fpscr);
212
213 // Start up mon in real-mode
214 #if ENABLE_MON
215 char *arg[4] = {"mon", "-m", "-r", NULL};
216 mon(3, arg);
217 #endif
218 QuitEmulator();
219 }
220
221
222 /*
223 * Record result in CR0
224 */
225
226 static void record(uint32 val)
227 {
228 uint32 crf = 0;
229 if (val == 0)
230 crf |= 0x20000000;
231 else if (val & 0x80000000)
232 crf |= 0x80000000;
233 else
234 crf |= 0x40000000;
235 if (xer & 0x80000000)
236 crf |= 0x10000000;
237 cr = (cr & 0x0fffffff) | crf;
238 }
239
240
241 /*
242 * Record result in CR1
243 */
244
245 static inline void record1(void)
246 {
247 cr = (cr & 0xf0ffffff) | ((fpscr >> 4) & 0x0f000000);
248 }
249
250
251 /*
252 * Convert mask begin/end to mask
253 */
254
255 static uint32 mbme2mask(uint32 op)
256 {
257 uint32 mb = (op >> 6) & 0x1f;
258 uint32 me = (op >> 1) & 0x1f;
259 uint32 m = 0;
260 uint32 i;
261
262 if (mb <= me)
263 for (i=mb; i<=me; i++)
264 m |= 0x80000000 >> i;
265 else {
266 for (i=0; i<=me; i++)
267 m |= 0x80000000 >> i;
268 for (i=mb; i<=31; i++)
269 m |= 0x80000000 >> i;
270 }
271 return m;
272 }
273
274
275 /*
276 * Emulate instruction with primary opcode = 19
277 */
278
279 static void emul19(uint32 op)
280 {
281 uint32 exop = (op >> 1) & 0x3ff;
282 uint32 rd = (op >> 21) & 0x1f;
283 uint32 ra = (op >> 16) & 0x1f;
284 switch (exop) {
285
286 case 0: { // mcrf
287 uint32 crfd = 0x1c - (rd & 0x1c);
288 uint32 crfa = 0x1c - (ra & 0x1c);
289 uint32 crf = (cr >> crfa) & 0xf;
290 cr = (cr & ~(0xf << crfd)) | (crf << crfd);
291 break;
292 }
293
294 case 16: { // bclr
295 uint32 oldpc = pc;
296 if (!(rd & 4)) {
297 ctr--;
298 if (rd & 2) {
299 if (ctr)
300 goto blr_nobranch;
301 } else {
302 if (!ctr)
303 goto blr_nobranch;
304 }
305 }
306 if (!(rd & 0x10)) {
307 if (rd & 8) {
308 if (!(cr & (0x80000000 >> ra)))
309 goto blr_nobranch;
310 } else {
311 if (cr & (0x80000000 >> ra))
312 goto blr_nobranch;
313 }
314 }
315 pc = lr & 0xfffffffc;
316 blr_nobranch:
317 if (op & 1)
318 lr = oldpc;
319 break;
320 }
321
322 case 33: // crnor
323 if ((cr & (0x80000000 >> ra)) || ((cr & (0x80000000 >> ((op >> 11) & 0x1f)))))
324 cr &= ~(0x80000000 >> rd);
325 else
326 cr |= 0x80000000 >> rd;
327 break;
328
329 case 129: // crandc
330 if ((cr & (0x80000000 >> ra)) && !((cr & (0x80000000 >> ((op >> 11) & 0x1f)))))
331 cr |= 0x80000000 >> rd;
332 else
333 cr &= ~(0x80000000 >> rd);
334 break;
335
336 case 150: // isync
337 break;
338
339 case 193: { // crxor
340 uint32 mask = 0x80000000 >> rd;
341 cr = (((((cr >> (31 - ra)) ^ (cr >> (31 - ((op >> 11) & 0x1f)))) & 1) << (31 - rd)) & mask) | (cr & ~mask);
342 break;
343 }
344
345 case 225: // crnand
346 if ((cr & (0x80000000 >> ra)) && ((cr & (0x80000000 >> ((op >> 11) & 0x1f)))))
347 cr &= ~(0x80000000 >> rd);
348 else
349 cr |= 0x80000000 >> rd;
350 break;
351
352 case 257: // crand
353 if ((cr & (0x80000000 >> ra)) && ((cr & (0x80000000 >> ((op >> 11) & 0x1f)))))
354 cr |= 0x80000000 >> rd;
355 else
356 cr &= ~(0x80000000 >> rd);
357 break;
358
359 case 289: { // creqv
360 uint32 mask = 0x80000000 >> rd;
361 cr = (((~((cr >> (31 - ra)) ^ (cr >> (31 - ((op >> 11) & 0x1f)))) & 1) << (31 - rd)) & mask) | (cr & ~mask);
362 break;
363 }
364
365 case 417: // crorc
366 if ((cr & (0x80000000 >> ra)) || !((cr & (0x80000000 >> ((op >> 11) & 0x1f)))))
367 cr |= 0x80000000 >> rd;
368 else
369 cr &= ~(0x80000000 >> rd);
370 break;
371
372 case 449: // cror
373 if ((cr & (0x80000000 >> ra)) || ((cr & (0x80000000 >> ((op >> 11) & 0x1f)))))
374 cr |= 0x80000000 >> rd;
375 else
376 cr &= ~(0x80000000 >> rd);
377 break;
378
379 case 528: { // bcctr
380 if (op & 1)
381 lr = pc;
382 if (!(rd & 4)) {
383 ctr--;
384 if (rd & 2) {
385 if (ctr)
386 goto bctr_nobranch;
387 } else {
388 if (!ctr)
389 goto bctr_nobranch;
390 }
391 }
392 if (!(rd & 0x10)) {
393 if (rd & 8) {
394 if (!(cr & (0x80000000 >> ra)))
395 goto bctr_nobranch;
396 } else {
397 if (cr & (0x80000000 >> ra))
398 goto bctr_nobranch;
399 }
400 }
401 pc = ctr & 0xfffffffc;
402 bctr_nobranch:
403 break;
404 }
405
406 default:
407 printf("Illegal 19 opcode %08x (exop %d) at %08x\n", op, exop, pc-4);
408 dump();
409 break;
410 }
411 }
412
413
414 /*
415 * Emulate instruction with primary opcode = 31
416 */
417
418 static void emul31(uint32 op)
419 {
420 uint32 exop = (op >> 1) & 0x3ff;
421 uint32 rd = (op >> 21) & 0x1f;
422 uint32 ra = (op >> 16) & 0x1f;
423 uint32 rb = (op >> 11) & 0x1f;
424 switch (exop) {
425
426 case 0: { // cmpw
427 uint32 crfd = 0x1c - (rd & 0x1c);
428 uint8 crf = 0;
429 if (r[ra] == r[rb])
430 crf |= 2;
431 else if ((int32)r[ra] < (int32)r[rb])
432 crf |= 8;
433 else
434 crf |= 4;
435 if (xer & 0x80000000)
436 crf |= 1;
437 cr = (cr & ~(0xf << crfd)) | (crf << crfd);
438 break;
439 }
440
441 case 8: { // subfc
442 uint64 tmp = (uint64)r[rb] - (uint64)r[ra];
443 r[rd] = tmp;
444 if (tmp & 0x100000000LL)
445 xer &= ~0x20000000;
446 else
447 xer |= 0x20000000;
448 if (op & 1)
449 record(r[rd]);
450 break;
451 }
452
453 case 10: { // addc
454 uint64 tmp = (uint64)r[ra] + (uint64)r[rb];
455 r[rd] = tmp;
456 if (tmp & 0x100000000LL)
457 xer |= 0x20000000;
458 else
459 xer &= ~0x20000000;
460 if (op & 1)
461 record(r[rd]);
462 break;
463 }
464
465 case 19: // mfcr
466 r[rd] = cr;
467 break;
468
469 case 20: // lwarx
470 r[rd] = ReadMacInt32(r[rb] + (ra ? r[ra] : 0));
471 //!! set reservation bit
472 break;
473
474 case 23: // lwzx
475 r[rd] = ReadMacInt32(r[rb] + (ra ? r[ra] : 0));
476 break;
477
478 case 24: // slw
479 r[ra] = r[rd] << (r[rb] & 0x3f);
480 if (op & 1)
481 record(r[ra]);
482 break;
483
484 case 26: { // cntlzw
485 uint32 mask = 0x80000000;
486 for (int i=0; i<32; i++, mask>>=1) {
487 if (r[rd] & mask) {
488 r[ra] = i;
489 goto cntlzw_done;
490 }
491 }
492 r[ra] = 32;
493 cntlzw_done:if (op & 1)
494 record(r[ra]);
495 break;
496 }
497
498 case 28: // and
499 r[ra] = r[rd] & r[rb];
500 if (op & 1)
501 record(r[ra]);
502 break;
503
504 case 32: { // cmplw
505 uint32 crfd = 0x1c - (rd & 0x1c);
506 uint8 crf = 0;
507 if (r[ra] == r[rb])
508 crf |= 2;
509 else if (r[ra] < r[rb])
510 crf |= 8;
511 else
512 crf |= 4;
513 if (xer & 0x80000000)
514 crf |= 1;
515 cr = (cr & ~(0xf << crfd)) | (crf << crfd);
516 break;
517 }
518
519 case 40: // subf
520 r[rd] = r[rb] - r[ra];
521 if (op & 1)
522 record(r[rd]);
523 break;
524
525 case 55: // lwzux
526 r[ra] += r[rb];
527 r[rd] = ReadMacInt32(r[ra]);
528 break;
529
530 case 60: // andc
531 r[ra] = r[rd] & ~r[rb];
532 if (op & 1)
533 record(r[ra]);
534 break;
535
536 case 75: // mulhw
537 r[rd] = ((int64)(int32)r[ra] * (int32)r[rb]) >> 32;
538 if (op & 1)
539 record(r[rd]);
540 break;
541
542 case 86: // dcbf
543 break;
544
545 case 87: // lbzx
546 r[rd] = ReadMacInt8(r[rb] + (ra ? r[ra] : 0));
547 break;
548
549 case 104: // neg
550 if (r[ra] == 0x80000000)
551 r[rd] = 0x80000000;
552 else
553 r[rd] = -(int32)r[ra];
554 if (op & 1)
555 record(r[rd]);
556 break;
557
558 case 119: // lbzux
559 r[ra] += r[rb];
560 r[rd] = ReadMacInt8(r[ra]);
561 break;
562
563 case 124: // nor
564 r[ra] = ~(r[rd] | r[rb]);
565 if (op & 1)
566 record(r[ra]);
567 break;
568
569 case 136: { // subfe
570 uint64 tmp = (uint64)r[rb] - (uint64)r[ra];
571 if (!(xer & 0x20000000))
572 tmp--;
573 r[rd] = tmp;
574 if (tmp & 0x100000000LL)
575 xer &= ~0x20000000;
576 else
577 xer |= 0x20000000;
578 if (op & 1)
579 record(r[rd]);
580 break;
581 }
582
583 case 138: { // adde
584 uint64 tmp = (uint64)r[ra] + (uint64)r[rb];
585 if (xer & 0x20000000)
586 tmp++;
587 r[rd] = tmp;
588 if (tmp & 0x100000000LL)
589 xer |= 0x20000000;
590 else
591 xer &= ~0x20000000;
592 if (op & 1)
593 record(r[rd]);
594 break;
595 }
596
597 case 144: { // mtcrf
598 uint32 mask = field2mask[(op >> 12) & 0xff];
599 cr = (r[rd] & mask) | (cr & ~mask);
600 break;
601 }
602
603 case 150: // stwcx
604 //!! check reserved bit
605 WriteMacInt32(r[rb] + (ra ? r[ra] : 0), r[rd]);
606 record(0);
607 break;
608
609 case 151: // stwx
610 WriteMacInt32(r[rb] + (ra ? r[ra] : 0), r[rd]);
611 break;
612
613 case 183: // stwux
614 r[ra] += r[rb];
615 WriteMacInt32(r[ra], r[rd]);
616 break;
617
618 case 215: // stbx
619 WriteMacInt8(r[rb] + (ra ? r[ra] : 0), r[rd]);
620 break;
621
622 case 235: // mullw
623 r[rd] = (int32)r[ra] * (int32)r[rb];
624 if (op & 1)
625 record(r[rd]);
626 break;
627
628 case 247: // stbux
629 r[ra] += r[rb];
630 WriteMacInt8(r[ra], r[rd]);
631 break;
632
633 case 266: // add
634 r[rd] = r[ra] + r[rb];
635 if (op & 1)
636 record(r[rd]);
637 break;
638
639 case 279: // lhzx
640 r[rd] = ReadMacInt16(r[rb] + (ra ? r[ra] : 0));
641 break;
642
643 case 284: // eqv
644 r[ra] = ~(r[rd] ^ r[rb]);
645 if (op & 1)
646 record(r[ra]);
647 break;
648
649 case 311: // lhzux
650 r[ra] += r[rb];
651 r[rd] = ReadMacInt16(r[ra]);
652 break;
653
654 case 316: // xor
655 r[ra] = r[rd] ^ r[rb];
656 if (op & 1)
657 record(r[ra]);
658 break;
659
660 case 339: { // mfspr
661 uint32 spr = ra | (rb << 5);
662 switch (spr) {
663 case 1: r[rd] = xer; break;
664 case 8: r[rd] = lr; break;
665 case 9: r[rd] = ctr; break;
666 default:
667 printf("Illegal mfspr opcode %08x at %08x\n", op, pc-4);
668 dump();
669 }
670 break;
671 }
672
673 case 343: // lhax
674 r[rd] = (int32)(int16)ReadMacInt16(r[rb] + (ra ? r[ra] : 0));
675 break;
676
677 case 371: // mftb
678 r[rd] = 0; //!!
679 break;
680
681 case 375: // lhaux
682 r[ra] += r[rb];
683 r[rd] = (int32)(int16)ReadMacInt16(r[ra]);
684 break;
685
686 case 407: // sthx
687 WriteMacInt16(r[rb] + (ra ? r[ra] : 0), r[rd]);
688 break;
689
690 case 412: // orc
691 r[ra] = r[rd] | ~r[rb];
692 if (op & 1)
693 record(r[ra]);
694 break;
695
696 case 439: // sthux
697 r[ra] += r[rb];
698 WriteMacInt16(r[ra], r[rd]);
699 break;
700
701 case 444: // or
702 r[ra] = r[rd] | r[rb];
703 if (op & 1)
704 record(r[ra]);
705 break;
706
707 case 459: // divwu
708 if (r[rb])
709 r[rd] = r[ra] / r[rb];
710 if (op & 1)
711 record(r[rd]);
712 break;
713
714 case 467: { // mtspr
715 uint32 spr = ra | (rb << 5);
716 switch (spr) {
717 case 1: xer = r[rd] & 0xe000007f; break;
718 case 8: lr = r[rd]; break;
719 case 9: ctr = r[rd]; break;
720 default:
721 printf("Illegal mtspr opcode %08x at %08x\n", op, pc-4);
722 dump();
723 }
724 break;
725 }
726
727 case 476: // nand
728 r[ra] = ~(r[rd] & r[rb]);
729 if (op & 1)
730 record(r[ra]);
731 break;
732
733 case 491: // divw
734 if (r[rb])
735 r[rd] = (int32)r[ra] / (int32)r[rb];
736 if (op & 1)
737 record(r[rd]);
738 break;
739
740 case 520: { // subfco
741 uint64 tmp = (uint64)r[rb] - (uint64)r[ra];
742 uint32 ov = (r[ra] ^ r[rb]) & ((uint32)tmp ^ r[rb]);
743 r[rd] = tmp;
744 if (tmp & 0x100000000LL)
745 xer &= ~0x20000000;
746 else
747 xer |= 0x20000000;
748 if (ov & 0x80000000)
749 xer |= 0xc0000000;
750 else
751 xer &= ~0x40000000;
752 if (op & 1)
753 record(r[rd]);
754 break;
755 }
756
757 case 522: { // addco
758 uint64 tmp = (uint64)r[ra] + (uint64)r[rb];
759 uint32 ov = (r[ra] ^ (uint32)tmp) & (r[rb] ^ (uint32)tmp);
760 r[rd] = tmp;
761 if (tmp & 0x100000000LL)
762 xer |= 0x20000000;
763 else
764 xer &= ~0x20000000;
765 if (ov & 0x80000000)
766 xer |= 0xc0000000;
767 else
768 xer &= ~0x40000000;
769 if (op & 1)
770 record(r[rd]);
771 break;
772 }
773
774 case 533: { // lswx
775 uint32 addr = r[rb] + (ra ? r[ra] : 0);
776 int nb = xer & 0x7f;
777 int reg = rd;
778 for (int i=0; i<nb; i++) {
779 switch (i & 3) {
780 case 0:
781 r[reg] = ReadMacInt8(addr + i) << 24;
782 break;
783 case 1:
784 r[reg] = (r[reg] & 0xff00ffff) | (ReadMacInt8(addr + i) << 16);
785 break;
786 case 2:
787 r[reg] = (r[reg] & 0xffff00ff) | (ReadMacInt8(addr + i) << 8);
788 break;
789 case 3:
790 r[reg] = (r[reg] & 0xffffff00) | ReadMacInt8(addr + i);
791 reg = (reg + 1) & 0x1f;
792 break;
793 }
794 }
795 break;
796 }
797
798 case 536: // srw
799 r[ra] = r[rd] >> (r[rb] & 0x3f);
800 if (op & 1)
801 record(r[ra]);
802 break;
803
804 case 597: { // lswi
805 uint32 addr = ra ? r[ra] : 0;
806 int nb = rb ? rb : 32;
807 int reg = rd;
808 for (int i=0; i<nb; i++) {
809 switch (i & 3) {
810 case 0:
811 r[reg] = ReadMacInt8(addr + i) << 24;
812 break;
813 case 1:
814 r[reg] = (r[reg] & 0xff00ffff) | (ReadMacInt8(addr + i) << 16);
815 break;
816 case 2:
817 r[reg] = (r[reg] & 0xffff00ff) | (ReadMacInt8(addr + i) << 8);
818 break;
819 case 3:
820 r[reg] = (r[reg] & 0xffffff00) | ReadMacInt8(addr + i);
821 reg = (reg + 1) & 0x1f;
822 break;
823 }
824 }
825 break;
826 }
827
828 case 598: // sync
829 break;
830
831 case 648: { // subfeo
832 uint64 tmp = (uint64)r[rb] - (uint64)r[ra];
833 if (!(xer & 0x20000000))
834 tmp--;
835 uint32 ov = (r[ra] ^ r[rb]) & ((uint32)tmp ^ r[rb]);
836 r[rd] = tmp;
837 if (tmp & 0x100000000LL)
838 xer &= ~0x20000000;
839 else
840 xer |= 0x20000000;
841 if (ov & 0x80000000)
842 xer |= 0xc0000000;
843 else
844 xer &= ~0x40000000;
845 if (op & 1)
846 record(r[rd]);
847 break;
848 }
849
850 case 650: { // addeo
851 uint64 tmp = (uint64)r[ra] + (uint64)r[rb];
852 if (xer & 0x20000000)
853 tmp++;
854 uint32 ov = (r[ra] ^ (uint32)tmp) & (r[rb] ^ (uint32)tmp);
855 r[rd] = tmp;
856 if (tmp & 0x100000000LL)
857 xer |= 0x20000000;
858 else
859 xer &= ~0x20000000;
860 if (ov & 0x80000000)
861 xer |= 0xc0000000;
862 else
863 xer &= ~0x40000000;
864 if (op & 1)
865 record(r[rd]);
866 break;
867 }
868
869 case 661: { // stswx
870 uint32 addr = r[rb] + (ra ? r[ra] : 0);
871 int nb = xer & 0x7f;
872 int reg = rd;
873 int shift = 24;
874 for (int i=0; i<nb; i++) {
875 WriteMacInt8(addr + i, (r[reg] >> shift));
876 shift -= 8;
877 if ((i & 3) == 3) {
878 shift = 24;
879 reg = (reg + 1) & 0x1f;
880 }
881 }
882 break;
883 }
884
885 case 725: { // stswi
886 uint32 addr = ra ? r[ra] : 0;
887 int nb = rb ? rb : 32;
888 int reg = rd;
889 int shift = 24;
890 for (int i=0; i<nb; i++) {
891 WriteMacInt8(addr + i, (r[reg] >> shift));
892 shift -= 8;
893 if ((i & 3) == 3) {
894 shift = 24;
895 reg = (reg + 1) & 0x1f;
896 }
897 }
898 break;
899 }
900
901 case 778: { // addo
902 uint32 tmp = r[ra] + r[rb];
903 uint32 ov = (r[ra] ^ tmp) & (r[rb] ^ tmp);
904 r[rd] = tmp;
905 if (ov & 0x80000000)
906 xer |= 0xc0000000;
907 else
908 xer &= ~0x40000000;
909 if (op & 1)
910 record(r[rd]);
911 break;
912 }
913
914 case 792: { // sraw
915 uint32 sh = r[rb] & 0x3f;
916 uint32 mask = ~(0xffffffff << sh);
917 if ((r[rd] & 0x80000000) && (r[rd] & mask))
918 xer |= 0x20000000;
919 else
920 xer &= ~0x20000000;
921 r[ra] = (int32)r[rd] >> sh;
922 if (op & 1)
923 record(r[ra]);
924 break;
925 }
926
927 case 824: { // srawi
928 uint32 mask = ~(0xffffffff << rb);
929 if ((r[rd] & 0x80000000) && (r[rd] & mask))
930 xer |= 0x20000000;
931 else
932 xer &= ~0x20000000;
933 r[ra] = (int32)r[rd] >> rb;
934 if (op & 1)
935 record(r[ra]);
936 break;
937 }
938
939 case 854: // eieio
940 break;
941
942 case 922: // extsh
943 r[ra] = (int32)(int16)r[rd];
944 if (op & 1)
945 record(r[ra]);
946 break;
947
948 case 954: // extsb
949 r[ra] = (int32)(int8)r[rd];
950 if (op & 1)
951 record(r[ra]);
952 break;
953
954 case 982: // icbi
955 break;
956
957 case 1003: // divwo
958 if (r[rb] == 0 || (r[ra] == 0x80000000 && r[rb] == 0xffffffff))
959 xer |= 0xc0000000;
960 else {
961 r[rd] = (int32)r[ra] / (int32)r[rb];
962 xer &= ~0x40000000;
963 }
964 if (op & 1)
965 record(r[rd]);
966 break;
967
968 #if 0
969 case 1014: // dcbz
970 memset(r[rb] + (ra ? r[ra] : 0), 0, 32);
971 break;
972 #endif
973
974 default:
975 printf("Illegal 31 opcode %08x (exop %d) at %08x\n", op, exop, pc-4);
976 dump();
977 break;
978 }
979 }
980
981
982 /*
983 * Emulate instruction with primary opcode = 59
984 */
985
986 static void emul59(uint32 op)
987 {
988 uint32 exop = (op >> 1) & 0x3ff;
989 switch (exop) {
990 default:
991 printf("Illegal 59 opcode %08x (exop %d) at %08x\n", op, exop, pc-4);
992 dump();
993 break;
994 }
995 }
996
997
998 /*
999 * Emulate instruction with primary opcode = 63
1000 */
1001
1002 static void emul63(uint32 op)
1003 {
1004 uint32 exop = (op >> 1) & 0x3ff;
1005 uint32 rd = (op >> 21) & 0x1f;
1006 uint32 ra = (op >> 16) & 0x1f;
1007 uint32 rb = (op >> 11) & 0x1f;
1008 switch (exop) {
1009
1010 case 583: // mffs
1011 fr[rd] = (double)(uint64)fpscr;
1012 if (op & 1)
1013 record1();
1014 break;
1015
1016 case 711: // mtfsf
1017 //!!
1018 if (op & 1)
1019 record1();
1020 break;
1021
1022 default:
1023 printf("Illegal 63 opcode %08x (exop %d) at %08x\n", op, exop, pc-4);
1024 dump();
1025 break;
1026 }
1027 }
1028
1029
1030 /*
1031 * Emulation loop
1032 */
1033
1034 void emul_ppc(uint32 start)
1035 {
1036 pc = start;
1037 //uint32 old_val = 0;
1038 for (;;) {
1039 //uint32 val = ReadMacInt32(0x68fff778);
1040 //if (val != old_val) {
1041 // printf("insn at %08lx changed %08lx->%08lx\n", pc-4, old_val, val);
1042 // old_val = val;
1043 //}
1044 uint32 op = ReadMacInt32(pc);
1045 #if FLIGHT_RECORDER
1046 record_step(op);
1047 #endif
1048 // printf("%08lx at %08lx\n", op, pc);
1049 uint32 primop = op >> 26;
1050 pc += 4;
1051 switch (primop) {
1052
1053 case 6: // SheepShaver extensions
1054 printf("Extended opcode %08x at %08x (68k pc %08x)\n", op, pc-4, r[24]);
1055 switch (op & 0x3f) {
1056 case 0: // EMUL_RETURN
1057 QuitEmulator();
1058 break;
1059
1060 case 1: // EXEC_RETURN
1061 //!!
1062 dump();
1063 break;
1064
1065 default: { // EMUL_OP
1066 M68kRegisters r68;
1067 WriteMacInt32(XLM_68K_R25, r[25]);
1068 WriteMacInt32(XLM_RUN_MODE, MODE_EMUL_OP);
1069 for (int i=0; i<8; i++)
1070 r68.d[i] = r[8 + i];
1071 for (int i=0; i<7; i++)
1072 r68.a[i] = r[16 + i];
1073 r68.a[7] = r[1];
1074 EmulOp(&r68, r[24], (op & 0x3f) - 2);
1075 for (int i=0; i<8; i++)
1076 r[8 + i] = r68.d[i];
1077 for (int i=0; i<7; i++)
1078 r[16 + i] = r68.a[i];
1079 r[1] = r68.a[7];
1080 WriteMacInt32(XLM_RUN_MODE, MODE_68K);
1081 break;
1082 }
1083 }
1084 break;
1085
1086 case 7: { // mulli
1087 uint32 rd = (op >> 21) & 0x1f;
1088 uint32 ra = (op >> 16) & 0x1f;
1089 r[rd] = (int32)r[ra] * (int32)(int16)(op & 0xffff);
1090 break;
1091 }
1092
1093 case 8: { // subfic
1094 uint32 rd = (op >> 21) & 0x1f;
1095 uint32 ra = (op >> 16) & 0x1f;
1096 uint64 tmp = (uint32)(int32)(int16)(op & 0xffff) - (uint64)r[ra];
1097 r[rd] = tmp;
1098 if (tmp & 0x100000000LL)
1099 xer &= ~0x20000000;
1100 else
1101 xer |= 0x20000000;
1102 break;
1103 }
1104
1105 case 10: { // cmpli
1106 uint32 crfd = 0x1c - ((op >> 21) & 0x1c);
1107 uint32 ra = (op >> 16) & 0x1f;
1108 uint32 val = (op & 0xffff);
1109 uint8 crf = 0;
1110 if (r[ra] == val)
1111 crf |= 2;
1112 else if (r[ra] < val)
1113 crf |= 8;
1114 else
1115 crf |= 4;
1116 if (xer & 0x80000000)
1117 crf |= 1;
1118 cr = (cr & ~(0xf << crfd)) | (crf << crfd);
1119 break;
1120 }
1121
1122 case 11: { // cmpi
1123 uint32 crfd = 0x1c - ((op >> 21) & 0x1c);
1124 uint32 ra = (op >> 16) & 0x1f;
1125 int32 val = (int32)(int16)(op & 0xffff);
1126 uint8 crf = 0;
1127 if ((int32)r[ra] == val)
1128 crf |= 2;
1129 else if ((int32)r[ra] < val)
1130 crf |= 8;
1131 else
1132 crf |= 4;
1133 if (xer & 0x80000000)
1134 crf |= 1;
1135 cr = (cr & ~(0xf << crfd)) | (crf << crfd);
1136 break;
1137 }
1138
1139 case 12: { // addic
1140 uint32 rd = (op >> 21) & 0x1f;
1141 uint32 ra = (op >> 16) & 0x1f;
1142 uint64 tmp = (uint64)r[ra] + (uint32)(int32)(int16)(op & 0xffff);
1143 r[rd] = tmp;
1144 if (tmp & 0x100000000LL)
1145 xer |= 0x20000000;
1146 else
1147 xer &= ~0x20000000;
1148 break;
1149 }
1150
1151 case 13: { // addic.
1152 uint32 rd = (op >> 21) & 0x1f;
1153 uint32 ra = (op >> 16) & 0x1f;
1154 uint64 tmp = (uint64)r[ra] + (uint32)(int32)(int16)(op & 0xffff);
1155 r[rd] = tmp;
1156 if (tmp & 0x100000000LL)
1157 xer |= 0x20000000;
1158 else
1159 xer &= ~0x20000000;
1160 record(r[rd]);
1161 break;
1162 }
1163
1164 case 14: { // addi
1165 uint32 rd = (op >> 21) & 0x1f;
1166 uint32 ra = (op >> 16) & 0x1f;
1167 r[rd] = (ra ? r[ra] : 0) + (int32)(int16)(op & 0xffff);
1168 break;
1169 }
1170
1171 case 15: { // addis
1172 uint32 rd = (op >> 21) & 0x1f;
1173 uint32 ra = (op >> 16) & 0x1f;
1174 r[rd] = (ra ? r[ra] : 0) + (op << 16);
1175 break;
1176 }
1177
1178 case 16: { // bc
1179 uint32 bo = (op >> 21) & 0x1f;
1180 uint32 bi = (op >> 16) & 0x1f;
1181 if (op & 1)
1182 lr = pc;
1183 if (!(bo & 4)) {
1184 ctr--;
1185 if (bo & 2) {
1186 if (ctr)
1187 goto bc_nobranch;
1188 } else {
1189 if (!ctr)
1190 goto bc_nobranch;
1191 }
1192 }
1193 if (!(bo & 0x10)) {
1194 if (bo & 8) {
1195 if (!(cr & (0x80000000 >> bi)))
1196 goto bc_nobranch;
1197 } else {
1198 if (cr & (0x80000000 >> bi))
1199 goto bc_nobranch;
1200 }
1201 }
1202 if (op & 2)
1203 pc = (int32)(int16)(op & 0xfffc);
1204 else
1205 pc += (int32)(int16)(op & 0xfffc) - 4;
1206 bc_nobranch:
1207 break;
1208 }
1209
1210 case 18: { // b
1211 int32 target = op & 0x03fffffc;
1212 if (target & 0x02000000)
1213 target |= 0xfc000000;
1214 if (op & 1)
1215 lr = pc;
1216 if (op & 2)
1217 pc = target;
1218 else
1219 pc += target - 4;
1220 break;
1221 }
1222
1223 case 19:
1224 emul19(op);
1225 break;
1226
1227 case 20: { // rlwimi
1228 uint32 rs = (op >> 21) & 0x1f;
1229 uint32 ra = (op >> 16) & 0x1f;
1230 uint32 sh = (op >> 11) & 0x1f;
1231 uint32 mask = mbme2mask(op);
1232 r[ra] = (((r[rs] << sh) | (r[rs] >> (32-sh))) & mask) | (r[ra] & ~mask);
1233 if (op & 1)
1234 record(r[ra]);
1235 break;
1236 }
1237
1238 case 21: { // rlwinm
1239 uint32 rs = (op >> 21) & 0x1f;
1240 uint32 ra = (op >> 16) & 0x1f;
1241 uint32 sh = (op >> 11) & 0x1f;
1242 r[ra] = ((r[rs] << sh) | (r[rs] >> (32-sh))) & mbme2mask(op);
1243 if (op & 1)
1244 record(r[ra]);
1245 break;
1246 }
1247
1248 case 23: { // rlwnm
1249 uint32 rs = (op >> 21) & 0x1f;
1250 uint32 ra = (op >> 16) & 0x1f;
1251 uint32 sh = r[(op >> 11) & 0x1f] & 0x1f;
1252 r[ra] = ((r[rs] << sh) | (r[rs] >> (32-sh))) & mbme2mask(op);
1253 if (op & 1)
1254 record(r[ra]);
1255 break;
1256 }
1257
1258 case 24: { // ori
1259 uint32 rs = (op >> 21) & 0x1f;
1260 uint32 ra = (op >> 16) & 0x1f;
1261 r[ra] = r[rs] | (op & 0xffff);
1262 break;
1263 }
1264
1265 case 25: { // oris
1266 uint32 rs = (op >> 21) & 0x1f;
1267 uint32 ra = (op >> 16) & 0x1f;
1268 r[ra] = r[rs] | (op << 16);
1269 break;
1270 }
1271
1272 case 26: { // xori
1273 uint32 rs = (op >> 21) & 0x1f;
1274 uint32 ra = (op >> 16) & 0x1f;
1275 r[ra] = r[rs] ^ (op & 0xffff);
1276 break;
1277 }
1278
1279 case 27: { // xoris
1280 uint32 rs = (op >> 21) & 0x1f;
1281 uint32 ra = (op >> 16) & 0x1f;
1282 r[ra] = r[rs] ^ (op << 16);
1283 break;
1284 }
1285
1286 case 28: { // andi.
1287 uint32 rs = (op >> 21) & 0x1f;
1288 uint32 ra = (op >> 16) & 0x1f;
1289 r[ra] = r[rs] & (op & 0xffff);
1290 record(r[ra]);
1291 break;
1292 }
1293
1294 case 29: { // andis.
1295 uint32 rs = (op >> 21) & 0x1f;
1296 uint32 ra = (op >> 16) & 0x1f;
1297 r[ra] = r[rs] & (op << 16);
1298 record(r[ra]);
1299 break;
1300 }
1301
1302 case 31:
1303 emul31(op);
1304 break;
1305
1306 case 32: { // lwz
1307 uint32 rd = (op >> 21) & 0x1f;
1308 uint32 ra = (op >> 16) & 0x1f;
1309 r[rd] = ReadMacInt32(int16(op & 0xffff) + (ra ? r[ra] : 0));
1310 break;
1311 }
1312
1313 case 33: { // lwzu
1314 uint32 rd = (op >> 21) & 0x1f;
1315 uint32 ra = (op >> 16) & 0x1f;
1316 r[ra] += int16(op & 0xffff);
1317 r[rd] = ReadMacInt32(r[ra]);
1318 break;
1319 }
1320
1321 case 34: { // lbz
1322 uint32 rd = (op >> 21) & 0x1f;
1323 uint32 ra = (op >> 16) & 0x1f;
1324 r[rd] = ReadMacInt8(int16(op & 0xffff) + (ra ? r[ra] : 0));
1325 break;
1326 }
1327
1328 case 35: { // lbzu
1329 uint32 rd = (op >> 21) & 0x1f;
1330 uint32 ra = (op >> 16) & 0x1f;
1331 r[ra] += int16(op & 0xffff);
1332 r[rd] = ReadMacInt8(r[ra]);
1333 break;
1334 }
1335
1336 case 36: { // stw
1337 uint32 rd = (op >> 21) & 0x1f;
1338 uint32 ra = (op >> 16) & 0x1f;
1339 WriteMacInt32(int16(op & 0xffff) + (ra ? r[ra] : 0), r[rd]);
1340 break;
1341 }
1342
1343 case 37: { // stwu
1344 uint32 rd = (op >> 21) & 0x1f;
1345 uint32 ra = (op >> 16) & 0x1f;
1346 r[ra] += int16(op & 0xffff);
1347 WriteMacInt32(r[ra], r[rd]);
1348 break;
1349 }
1350
1351 case 38: { // stb
1352 uint32 rd = (op >> 21) & 0x1f;
1353 uint32 ra = (op >> 16) & 0x1f;
1354 WriteMacInt8(int16(op & 0xffff) + (ra ? r[ra] : 0), r[rd]);
1355 break;
1356 }
1357
1358 case 39: { // stbu
1359 uint32 rd = (op >> 21) & 0x1f;
1360 uint32 ra = (op >> 16) & 0x1f;
1361 r[ra] += int16(op & 0xffff);
1362 WriteMacInt8(r[ra], r[rd]);
1363 break;
1364 }
1365
1366 case 40: { // lhz
1367 uint32 rd = (op >> 21) & 0x1f;
1368 uint32 ra = (op >> 16) & 0x1f;
1369 r[rd] = ReadMacInt16(int16(op & 0xffff) + (ra ? r[ra] : 0));
1370 break;
1371 }
1372
1373 case 41: { // lhzu
1374 uint32 rd = (op >> 21) & 0x1f;
1375 uint32 ra = (op >> 16) & 0x1f;
1376 r[ra] += int16(op & 0xffff);
1377 r[rd] = ReadMacInt16(r[ra]);
1378 break;
1379 }
1380
1381 case 42: { // lha
1382 uint32 rd = (op >> 21) & 0x1f;
1383 uint32 ra = (op >> 16) & 0x1f;
1384 r[rd] = (int32)(int16)ReadMacInt16(int16(op & 0xffff) + (ra ? r[ra] : 0));
1385 break;
1386 }
1387
1388 case 43: { // lhau
1389 uint32 rd = (op >> 21) & 0x1f;
1390 uint32 ra = (op >> 16) & 0x1f;
1391 r[ra] += int16(op & 0xffff);
1392 r[rd] = (int32)(int16)ReadMacInt16(r[ra]);
1393 break;
1394 }
1395
1396 case 44: { // sth
1397 uint32 rd = (op >> 21) & 0x1f;
1398 uint32 ra = (op >> 16) & 0x1f;
1399 WriteMacInt16(int16(op & 0xffff) + (ra ? r[ra] : 0), r[rd]);
1400 break;
1401 }
1402
1403 case 45: { // sthu
1404 uint32 rd = (op >> 21) & 0x1f;
1405 uint32 ra = (op >> 16) & 0x1f;
1406 r[ra] += int16(op & 0xffff);
1407 WriteMacInt16(r[ra], r[rd]);
1408 break;
1409 }
1410
1411 case 46: { // lmw
1412 uint32 rd = (op >> 21) & 0x1f;
1413 uint32 ra = (op >> 16) & 0x1f;
1414 uint32 addr = int16(op & 0xffff) + (ra ? r[ra] : 0);
1415 while (rd <= 31) {
1416 r[rd] = ReadMacInt32(addr);
1417 rd++;
1418 addr += 4;
1419 }
1420 break;
1421 }
1422
1423 case 47: { // stmw
1424 uint32 rd = (op >> 21) & 0x1f;
1425 uint32 ra = (op >> 16) & 0x1f;
1426 uint32 addr = int16(op & 0xffff) + (ra ? r[ra] : 0);
1427 while (rd <= 31) {
1428 WriteMacInt32(addr, r[rd]);
1429 rd++;
1430 addr += 4;
1431 }
1432 break;
1433 }
1434
1435 case 50: { // lfd
1436 uint32 rd = (op >> 21) & 0x1f;
1437 uint32 ra = (op >> 16) & 0x1f;
1438 fr[rd] = (double)ReadMacInt64(int16(op & 0xffff) + (ra ? r[ra] : 0));
1439 break;
1440 }
1441
1442 case 54: { // stfd
1443 uint32 rd = (op >> 21) & 0x1f;
1444 uint32 ra = (op >> 16) & 0x1f;
1445 WriteMacInt64(int16(op & 0xffff) + (ra ? r[ra] : 0), (uint64)fr[rd]);
1446 break;
1447 }
1448
1449 case 59:
1450 emul59(op);
1451 break;
1452
1453 case 63:
1454 emul63(op);
1455 break;
1456
1457 default:
1458 printf("Illegal opcode %08x at %08x\n", op, pc-4);
1459 dump();
1460 break;
1461 }
1462 }
1463 }
1464
1465
1466 static struct sigaction sigsegv_action;
1467
1468 static void sigsegv_handler(int sig)
1469 {
1470 printf("SIGSEGV\n");
1471 dump();
1472 }
1473
1474 void init_emul_ppc(void)
1475 {
1476 // Init field2mask
1477 for (int i=0; i<256; i++) {
1478 uint32 mask = 0;
1479 if (i & 0x01) mask |= 0x0000000f;
1480 if (i & 0x02) mask |= 0x000000f0;
1481 if (i & 0x04) mask |= 0x00000f00;
1482 if (i & 0x08) mask |= 0x0000f000;
1483 if (i & 0x10) mask |= 0x000f0000;
1484 if (i & 0x20) mask |= 0x00f00000;
1485 if (i & 0x40) mask |= 0x0f000000;
1486 if (i & 0x80) mask |= 0xf0000000;
1487 field2mask[i] = mask;
1488 }
1489
1490 // Init registers
1491 for (int i=0; i<32; i++) {
1492 r[i] = 0;
1493 fr[i] = 0.0;
1494 }
1495 lr = ctr = 0;
1496 cr = xer = 0;
1497 fpscr = 0;
1498
1499 r[3] = ROMBase + 0x30d000;
1500
1501 // Install SIGSEGV handler
1502 sigemptyset(&sigsegv_action.sa_mask);
1503 sigsegv_action.sa_handler = (__sighandler_t)sigsegv_handler;
1504 sigsegv_action.sa_flags = 0;
1505 sigsegv_action.sa_restorer = NULL;
1506 sigaction(SIGSEGV, &sigsegv_action, NULL);
1507
1508 #if FLIGHT_RECORDER && ENABLE_MON
1509 // Install "log" command in mon
1510 mon_add_command("log", dump_log, "log Dump PowerPC emulation log\n");
1511 #endif
1512 }
1513
1514
1515 /*
1516 * Execute 68k subroutine (must be ended with EXEC_RETURN)
1517 * This must only be called by the emul_thread when in EMUL_OP mode
1518 * r->a[7] is unused, the routine runs on the caller's stack
1519 */
1520
1521 void Execute68k(uint32 pc, M68kRegisters *r)
1522 {
1523 printf("ERROR: Execute68k() unimplemented\n");
1524 QuitEmulator();
1525 }
1526
1527
1528 /*
1529 * Execute 68k A-Trap from EMUL_OP routine
1530 * r->a[7] is unused, the routine runs on the caller's stack
1531 */
1532
1533 void Execute68kTrap(uint16 trap, M68kRegisters *r)
1534 {
1535 printf("ERROR: Execute68kTrap() unimplemented\n");
1536 QuitEmulator();
1537 }
1538
1539
1540 /*
1541 * Call MacOS PPC code
1542 */
1543
1544 uint32 call_macos(uint32 tvect)
1545 {
1546 printf("ERROR: call_macos() unimplemented\n");
1547 QuitEmulator();
1548 return 0;
1549 }
1550
1551 uint32 call_macos1(uint32 tvect, uint32 arg1)
1552 {
1553 printf("ERROR: call_macos1() unimplemented\n");
1554 QuitEmulator();
1555 return 0;
1556 }
1557
1558 uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2)
1559 {
1560 printf("ERROR: call_macos2() unimplemented\n");
1561 QuitEmulator();
1562 return 0;
1563 }
1564
1565 uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3)
1566 {
1567 printf("ERROR: call_macos3() unimplemented\n");
1568 QuitEmulator();
1569 return 0;
1570 }
1571
1572 uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4)
1573 {
1574 printf("ERROR: call_macos4() unimplemented\n");
1575 QuitEmulator();
1576 return 0;
1577 }
1578
1579 uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5)
1580 {
1581 printf("ERROR: call_macos5() unimplemented\n");
1582 QuitEmulator();
1583 return 0;
1584 }
1585
1586 uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6)
1587 {
1588 printf("ERROR: call_macos6() unimplemented\n");
1589 QuitEmulator();
1590 return 0;
1591 }
1592
1593 uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7)
1594 {
1595 printf("ERROR: call_macos7() unimplemented\n");
1596 QuitEmulator();
1597 return 0;
1598 }
1599
1600
1601 /*
1602 * Atomic operations
1603 */
1604
1605 extern int atomic_add(int *var, int v)
1606 {
1607 int ret = *var;
1608 *var += v;
1609 return ret;
1610 }
1611
1612 extern int atomic_and(int *var, int v)
1613 {
1614 int ret = *var;
1615 *var &= v;
1616 return ret;
1617 }
1618
1619 extern int atomic_or(int *var, int v)
1620 {
1621 int ret = *var;
1622 *var |= v;
1623 return ret;
1624 }
1625
1626
1627 extern "C" void get_resource(void);
1628 extern "C" void get_1_resource(void);
1629 extern "C" void get_ind_resource(void);
1630 extern "C" void get_1_ind_resource(void);
1631 extern "C" void r_get_resource(void);
1632
1633 void get_resource(void)
1634 {
1635 printf("ERROR: get_resource() unimplemented\n");
1636 QuitEmulator();
1637 }
1638
1639 void get_1_resource(void)
1640 {
1641 printf("ERROR: get_1_resource() unimplemented\n");
1642 QuitEmulator();
1643 }
1644
1645 void get_ind_resource(void)
1646 {
1647 printf("ERROR: get_ind_resource() unimplemented\n");
1648 QuitEmulator();
1649 }
1650
1651 void get_1_ind_resource(void)
1652 {
1653 printf("ERROR: get_1_ind_resource() unimplemented\n");
1654 QuitEmulator();
1655 }
1656
1657 void r_get_resource(void)
1658 {
1659 printf("ERROR: r_get_resource() unimplemented\n");
1660 QuitEmulator();
1661 }