1 |
/* |
2 |
* emul_ppc.cpp - PowerPC processor emulation |
3 |
* |
4 |
* SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig |
5 |
* |
6 |
* This program is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* This program is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
*/ |
20 |
|
21 |
/* |
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] = ROM_BASE + 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 |
} |