1 |
cebix |
1.1 |
/* |
2 |
|
|
* emul_ppc.cpp - PowerPC processor emulation |
3 |
|
|
* |
4 |
gbeauche |
1.3 |
* SheepShaver (C) 1997-2005 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 |
|
|
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 |
|
|
} |