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

# User Rev Content
1 cebix 1.1 /*
2     * emul_ppc.cpp - PowerPC processor emulation
3     *
4 gbeauche 1.4 * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5 cebix 1.1 *
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 asvitkine 1.5 r[3] = ROMBase + 0x30d000;
1500 cebix 1.1
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     }