/[gxemul]/trunk/src/cpus/cpu_ppc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_ppc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 51647 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


1 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc.c,v 1.59 2006/06/24 21:47:23 debug Exp $
29 *
30 * PowerPC/POWER CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "cpu.h"
39 #include "devices.h"
40 #include "machine.h"
41 #include "memory.h"
42 #include "misc.h"
43 #include "of.h"
44 #include "opcodes_ppc.h"
45 #include "ppc_bat.h"
46 #include "ppc_pte.h"
47 #include "ppc_spr.h"
48 #include "ppc_spr_strings.h"
49 #include "symbol.h"
50
51 #define DYNTRANS_DUALMODE_32
52 #include "tmp_ppc_head.c"
53
54
55 void ppc_pc_to_pointers(struct cpu *);
56 void ppc32_pc_to_pointers(struct cpu *);
57
58
59 /*
60 * ppc_cpu_new():
61 *
62 * Create a new PPC cpu object.
63 *
64 * Returns 1 on success, 0 if there was no matching PPC processor with
65 * this cpu_type_name.
66 */
67 int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
68 int cpu_id, char *cpu_type_name)
69 {
70 int any_cache = 0;
71 int i, found;
72 struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
73
74 /* Scan the cpu_type_defs list for this cpu type: */
75 i = 0;
76 found = -1;
77 while (i >= 0 && cpu_type_defs[i].name != NULL) {
78 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
79 found = i;
80 break;
81 }
82 i++;
83 }
84 if (found == -1)
85 return 0;
86
87 cpu->memory_rw = ppc_memory_rw;
88
89 cpu->cd.ppc.cpu_type = cpu_type_defs[found];
90 cpu->name = cpu->cd.ppc.cpu_type.name;
91 cpu->byte_order = EMUL_BIG_ENDIAN;
92 cpu->cd.ppc.mode = MODE_PPC; /* TODO */
93
94 /* Current operating mode: */
95 cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
96 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
97
98 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
99 PPC_MSR_SF | PPC_MSR_FP; */
100
101 cpu->cd.ppc.spr[SPR_IBAT0U] = 0x00001ffc | BAT_Vs;
102 cpu->cd.ppc.spr[SPR_IBAT0L] = 0x00000000 | BAT_PP_RW;
103 cpu->cd.ppc.spr[SPR_IBAT1U] = 0xc0001ffc | BAT_Vs;
104 cpu->cd.ppc.spr[SPR_IBAT1L] = 0x00000000 | BAT_PP_RW;
105 cpu->cd.ppc.spr[SPR_IBAT3U] = 0xf0001ffc | BAT_Vs;
106 cpu->cd.ppc.spr[SPR_IBAT3L] = 0xf0000000 | BAT_PP_RW;
107 cpu->cd.ppc.spr[SPR_DBAT0U] = 0x00001ffc | BAT_Vs;
108 cpu->cd.ppc.spr[SPR_DBAT0L] = 0x00000000 | BAT_PP_RW;
109 cpu->cd.ppc.spr[SPR_DBAT1U] = 0xc0001ffc | BAT_Vs;
110 cpu->cd.ppc.spr[SPR_DBAT1L] = 0x00000000 | BAT_PP_RW;
111 cpu->cd.ppc.spr[SPR_DBAT2U] = 0xe0001ffc | BAT_Vs;
112 cpu->cd.ppc.spr[SPR_DBAT2L] = 0xe0000000 | BAT_PP_RW;
113 cpu->cd.ppc.spr[SPR_DBAT3U] = 0xf0001ffc | BAT_Vs;
114 cpu->cd.ppc.spr[SPR_DBAT3L] = 0xf0000000 | BAT_PP_RW;
115
116 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
117
118 if (cpu->is_32bit) {
119 cpu->update_translation_table = ppc32_update_translation_table;
120 cpu->invalidate_translation_caches =
121 ppc32_invalidate_translation_caches;
122 cpu->invalidate_code_translation =
123 ppc32_invalidate_code_translation;
124 } else {
125 cpu->update_translation_table = ppc_update_translation_table;
126 cpu->invalidate_translation_caches =
127 ppc_invalidate_translation_caches;
128 cpu->invalidate_code_translation =
129 ppc_invalidate_code_translation;
130 }
131
132 cpu->translate_v2p = ppc_translate_v2p;
133
134 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
135 if (cpu_id == 0) {
136 debug("%s", cpu->cd.ppc.cpu_type.name);
137
138 if (cpu->cd.ppc.cpu_type.icache_shift != 0)
139 any_cache = 1;
140 if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
141 any_cache = 1;
142 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
143 any_cache = 1;
144
145 if (any_cache) {
146 debug(" (I+D = %i+%i KB",
147 (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
148 (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
149 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
150 debug(", L2 = %i KB",
151 (int)(1 << (cpu->cd.ppc.cpu_type.
152 l2cache_shift-10)));
153 }
154 debug(")");
155 }
156 }
157
158 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
159
160 /* Some default stack pointer value. TODO: move this? */
161 cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
162
163 /*
164 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
165 */
166 if (cpu->machine->prom_emulation)
167 cpu->cd.ppc.of_emul_addr = 0xfff00000;
168
169 return 1;
170 }
171
172
173 /*
174 * ppc_cpu_list_available_types():
175 *
176 * Print a list of available PPC CPU types.
177 */
178 void ppc_cpu_list_available_types(void)
179 {
180 int i, j;
181 struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
182
183 i = 0;
184 while (tdefs[i].name != NULL) {
185 debug("%s", tdefs[i].name);
186 for (j=10 - strlen(tdefs[i].name); j>0; j--)
187 debug(" ");
188 i++;
189 if ((i % 6) == 0 || tdefs[i].name == NULL)
190 debug("\n");
191 }
192 }
193
194
195 /*
196 * ppc_cpu_dumpinfo():
197 */
198 void ppc_cpu_dumpinfo(struct cpu *cpu)
199 {
200 struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
201
202 debug(" (%i-bit ", cpu->cd.ppc.bits);
203
204 switch (cpu->cd.ppc.mode) {
205 case MODE_PPC:
206 debug("PPC");
207 break;
208 case MODE_POWER:
209 debug("POWER");
210 break;
211 default:
212 debug("_INTERNAL ERROR_");
213 }
214
215 debug(", I+D = %i+%i KB",
216 (1 << ct->icache_shift) / 1024,
217 (1 << ct->dcache_shift) / 1024);
218
219 if (ct->l2cache_shift) {
220 int kb = (1 << ct->l2cache_shift) / 1024;
221 debug(", L2 = %i %cB",
222 kb >= 1024? kb / 1024 : kb,
223 kb >= 1024? 'M' : 'K');
224 }
225
226 debug(")\n");
227 }
228
229
230 /*
231 * reg_access_msr():
232 */
233 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
234 int check_for_interrupts)
235 {
236 uint64_t old = cpu->cd.ppc.msr;
237
238 if (valuep == NULL) {
239 fatal("reg_access_msr(): NULL\n");
240 return;
241 }
242
243 if (writeflag) {
244 cpu->cd.ppc.msr = *valuep;
245
246 /* Switching between temporary and real gpr 0..3? */
247 if ((old & PPC_MSR_TGPR) != (cpu->cd.ppc.msr & PPC_MSR_TGPR)) {
248 int i;
249 for (i=0; i<PPC_N_TGPRS; i++) {
250 uint64_t t = cpu->cd.ppc.gpr[i];
251 cpu->cd.ppc.gpr[i] = cpu->cd.ppc.tgpr[i];
252 cpu->cd.ppc.tgpr[i] = t;
253 }
254 }
255
256 if (cpu->cd.ppc.msr & PPC_MSR_IP) {
257 fatal("\n[ Reboot hack for NetBSD/prep. TODO: "
258 "fix this. ]\n");
259 cpu->running = 0;
260 }
261 }
262
263 /* TODO: Is the little-endian bit writable? */
264
265 cpu->cd.ppc.msr &= ~PPC_MSR_LE;
266 if (cpu->byte_order != EMUL_BIG_ENDIAN)
267 cpu->cd.ppc.msr |= PPC_MSR_LE;
268
269 if (!writeflag)
270 *valuep = cpu->cd.ppc.msr;
271
272 if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
273 if (cpu->cd.ppc.dec_intr_pending) {
274 ppc_exception(cpu, PPC_EXCEPTION_DEC);
275 cpu->cd.ppc.dec_intr_pending = 0;
276 } else if (cpu->cd.ppc.irq_asserted)
277 ppc_exception(cpu, PPC_EXCEPTION_EI);
278 }
279 }
280
281
282 /*
283 * ppc_exception():
284 */
285 void ppc_exception(struct cpu *cpu, int exception_nr)
286 {
287 /* Save PC and MSR: */
288 cpu->cd.ppc.spr[SPR_SRR0] = cpu->pc;
289
290 if (exception_nr >= 0x10 && exception_nr <= 0x13)
291 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0xffff)
292 | (cpu->cd.ppc.cr & 0xf0000000);
293 else
294 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0x87c0ffff);
295
296 if (!quiet_mode)
297 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
298 (long long)cpu->pc);
299
300 /* Disable External Interrupts, Recoverable Interrupt Mode,
301 and go to Supervisor mode */
302 cpu->cd.ppc.msr &= ~(PPC_MSR_EE | PPC_MSR_RI | PPC_MSR_PR);
303
304 cpu->pc = exception_nr * 0x100;
305 if (cpu->cd.ppc.msr & PPC_MSR_IP)
306 cpu->pc += 0xfff00000ULL;
307
308 if (cpu->is_32bit)
309 ppc32_pc_to_pointers(cpu);
310 else
311 ppc_pc_to_pointers(cpu);
312 }
313
314
315 /*
316 * ppc_cpu_register_dump():
317 *
318 * Dump cpu registers in a relatively readable format.
319 *
320 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
321 * coprocs: if bit i is set, then we should dump registers from coproc i.
322 */
323 void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
324 {
325 char *symbol;
326 uint64_t offset, tmp;
327 int i, x = cpu->cpu_id;
328 int bits32 = cpu->cd.ppc.bits == 32;
329
330 if (gprs) {
331 /* Special registers (pc, ...) first: */
332 symbol = get_symbol_name(&cpu->machine->symbol_context,
333 cpu->pc, &offset);
334
335 debug("cpu%i: pc = 0x", x);
336 if (bits32)
337 debug("%08"PRIx32, (uint32_t)cpu->pc);
338 else
339 debug("%016"PRIx64, (uint64_t)cpu->pc);
340 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
341
342 debug("cpu%i: lr = 0x", x);
343 if (bits32)
344 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
345 else
346 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
347 debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
348
349 if (bits32)
350 debug(" ");
351 else
352 debug("\ncpu%i: ", x);
353 debug("ctr = 0x", x);
354 if (bits32)
355 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
356 else
357 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
358
359 debug(" xer = 0x", x);
360 if (bits32)
361 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
362 else
363 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
364
365 debug("\n");
366
367 if (bits32) {
368 /* 32-bit: */
369 for (i=0; i<PPC_NGPRS; i++) {
370 if ((i % 4) == 0)
371 debug("cpu%i:", x);
372 debug(" r%02i = 0x%08x ", i,
373 (int)cpu->cd.ppc.gpr[i]);
374 if ((i % 4) == 3)
375 debug("\n");
376 }
377 } else {
378 /* 64-bit: */
379 for (i=0; i<PPC_NGPRS; i++) {
380 int r = (i >> 1) + ((i & 1) << 4);
381 if ((i % 2) == 0)
382 debug("cpu%i:", x);
383 debug(" r%02i = 0x%016llx ", r,
384 (long long)cpu->cd.ppc.gpr[r]);
385 if ((i % 2) == 1)
386 debug("\n");
387 }
388 }
389
390 /* Other special registers: */
391 if (bits32) {
392 debug("cpu%i: srr0 = 0x%08x srr1 = 0x%08x\n", x,
393 (int)cpu->cd.ppc.spr[SPR_SRR0],
394 (int)cpu->cd.ppc.spr[SPR_SRR1]);
395 } else {
396 debug("cpu%i: srr0 = 0x%016llx srr1 = 0x%016llx\n", x,
397 (long long)cpu->cd.ppc.spr[SPR_SRR0],
398 (long long)cpu->cd.ppc.spr[SPR_SRR1]);
399 }
400 debug("cpu%i: msr = ", x);
401 reg_access_msr(cpu, &tmp, 0, 0);
402 if (bits32)
403 debug("0x%08x ", (int)tmp);
404 else
405 debug("0x%016llx ", (long long)tmp);
406 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
407 (int)cpu->cd.ppc.spr[SPR_TBL]);
408 debug("cpu%i: dec = 0x%08x", x, (int)cpu->cd.ppc.spr[SPR_DEC]);
409 if (!bits32)
410 debug(" hdec = 0x%08x\n",
411 (int)cpu->cd.ppc.spr[SPR_HDEC]);
412 debug("\n");
413 }
414
415 if (coprocs & 1) {
416 debug("cpu%i: fpscr = 0x%08x\n", x, (int)cpu->cd.ppc.fpscr);
417
418 /* TODO: show floating-point values :-) */
419
420 /* TODO: 32-bit fprs on 32-bit PPC cpus? */
421
422 for (i=0; i<PPC_NFPRS; i++) {
423 if ((i % 2) == 0)
424 debug("cpu%i:", x);
425 debug(" f%02i = 0x%016llx ", i,
426 (long long)cpu->cd.ppc.fpr[i]);
427 if ((i % 2) == 1)
428 debug("\n");
429 }
430 }
431
432 if (coprocs & 2) {
433 debug("cpu%i: sdr1 = 0x%llx\n", x,
434 (long long)cpu->cd.ppc.spr[SPR_SDR1]);
435 if (cpu->cd.ppc.cpu_type.flags & PPC_601)
436 debug("cpu%i: PPC601-style, TODO!\n");
437 else {
438 for (i=0; i<8; i++) {
439 int spr = SPR_IBAT0U + i*2;
440 uint32_t upper = cpu->cd.ppc.spr[spr];
441 uint32_t lower = cpu->cd.ppc.spr[spr+1];
442 uint32_t len = (((upper & BAT_BL) << 15)
443 | 0x1ffff) + 1;
444 debug("cpu%i: %sbat%i: u=0x%08x l=0x%08x ",
445 x, i<4? "i" : "d", i&3, upper, lower);
446 if (!(upper & BAT_V)) {
447 debug(" (not valid)\n");
448 continue;
449 }
450 if (len < 1048576)
451 debug(" (%i KB, ", len >> 10);
452 else
453 debug(" (%i MB, ", len >> 20);
454 if (upper & BAT_Vu)
455 debug("user, ");
456 if (upper & BAT_Vs)
457 debug("supervisor, ");
458 if (lower & (BAT_W | BAT_I | BAT_M | BAT_G))
459 debug("%s%s%s%s, ",
460 lower & BAT_W? "W" : "",
461 lower & BAT_I? "I" : "",
462 lower & BAT_M? "M" : "",
463 lower & BAT_G? "G" : "");
464 switch (lower & BAT_PP) {
465 case BAT_PP_NONE: debug("NO access"); break;
466 case BAT_PP_RO_S: debug("read-only, soft");
467 break;
468 case BAT_PP_RO: debug("read-only"); break;
469 case BAT_PP_RW: debug("read/write"); break;
470 }
471 debug(")\n");
472 }
473 }
474 }
475
476 if (coprocs & 4) {
477 for (i=0; i<16; i++) {
478 uint32_t s = cpu->cd.ppc.sr[i];
479 debug("cpu%i:", x);
480 debug(" sr%2i = 0x%08x", i, (int)s);
481 s &= (SR_TYPE | SR_SUKEY | SR_PRKEY | SR_NOEXEC);
482 if (s != 0) {
483 debug(" (");
484 if (s & SR_TYPE) {
485 debug("NON-memory type");
486 s &= ~SR_TYPE;
487 if (s != 0)
488 debug(", ");
489 }
490 if (s & SR_SUKEY) {
491 debug("supervisor-key");
492 s &= ~SR_SUKEY;
493 if (s != 0)
494 debug(", ");
495 }
496 if (s & SR_PRKEY) {
497 debug("user-key");
498 s &= ~SR_PRKEY;
499 if (s != 0)
500 debug(", ");
501 }
502 if (s & SR_NOEXEC)
503 debug("NOEXEC");
504 debug(")");
505 }
506 debug("\n");
507 }
508 }
509 }
510
511
512 /*
513 * ppc_cpu_register_match():
514 */
515 void ppc_cpu_register_match(struct machine *m, char *name,
516 int writeflag, uint64_t *valuep, int *match_register)
517 {
518 int cpunr = 0;
519
520 /* CPU number: */
521
522 /* TODO */
523
524 /* Register name: */
525 if (strcasecmp(name, "pc") == 0) {
526 if (writeflag) {
527 m->cpus[cpunr]->pc = *valuep;
528 } else
529 *valuep = m->cpus[cpunr]->pc;
530 *match_register = 1;
531 } else if (strcasecmp(name, "msr") == 0) {
532 if (writeflag)
533 m->cpus[cpunr]->cd.ppc.msr = *valuep;
534 else
535 *valuep = m->cpus[cpunr]->cd.ppc.msr;
536 *match_register = 1;
537 } else if (strcasecmp(name, "lr") == 0) {
538 if (writeflag)
539 m->cpus[cpunr]->cd.ppc.spr[SPR_LR] = *valuep;
540 else
541 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_LR];
542 *match_register = 1;
543 } else if (strcasecmp(name, "cr") == 0) {
544 if (writeflag)
545 m->cpus[cpunr]->cd.ppc.cr = *valuep;
546 else
547 *valuep = m->cpus[cpunr]->cd.ppc.cr;
548 *match_register = 1;
549 } else if (strcasecmp(name, "dec") == 0) {
550 if (writeflag)
551 m->cpus[cpunr]->cd.ppc.spr[SPR_DEC] = *valuep;
552 else
553 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_DEC];
554 *match_register = 1;
555 } else if (strcasecmp(name, "hdec") == 0) {
556 if (writeflag)
557 m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC] = *valuep;
558 else
559 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC];
560 *match_register = 1;
561 } else if (strcasecmp(name, "ctr") == 0) {
562 if (writeflag)
563 m->cpus[cpunr]->cd.ppc.spr[SPR_CTR] = *valuep;
564 else
565 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_CTR];
566 *match_register = 1;
567 } else if (name[0] == 'r' && isdigit((int)name[1])) {
568 int nr = atoi(name + 1);
569 if (nr >= 0 && nr < PPC_NGPRS) {
570 if (writeflag) {
571 m->cpus[cpunr]->cd.ppc.gpr[nr] = *valuep;
572 } else
573 *valuep = m->cpus[cpunr]->cd.ppc.gpr[nr];
574 *match_register = 1;
575 }
576 } else if (strcasecmp(name, "xer") == 0) {
577 if (writeflag)
578 m->cpus[cpunr]->cd.ppc.spr[SPR_XER] = *valuep;
579 else
580 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_XER];
581 *match_register = 1;
582 } else if (strcasecmp(name, "fpscr") == 0) {
583 if (writeflag)
584 m->cpus[cpunr]->cd.ppc.fpscr = *valuep;
585 else
586 *valuep = m->cpus[cpunr]->cd.ppc.fpscr;
587 *match_register = 1;
588 } else if (name[0] == 'f' && isdigit((int)name[1])) {
589 int nr = atoi(name + 1);
590 if (nr >= 0 && nr < PPC_NFPRS) {
591 if (writeflag) {
592 m->cpus[cpunr]->cd.ppc.fpr[nr] = *valuep;
593 } else
594 *valuep = m->cpus[cpunr]->cd.ppc.fpr[nr];
595 *match_register = 1;
596 }
597 }
598 }
599
600
601 /*
602 * ppc_cpu_tlbdump():
603 *
604 * Not currently used for PPC.
605 */
606 void ppc_cpu_tlbdump(struct machine *m, int x, int rawflag)
607 {
608 }
609
610
611 static void add_response_word(struct cpu *cpu, char *r, uint64_t value,
612 size_t maxlen, int len)
613 {
614 char *format = (len == 4)? "%08"PRIx64 : "%016"PRIx64;
615 if (len == 4)
616 value &= 0xffffffffULL;
617 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
618 if (len == 4) {
619 value = ((value & 0xff) << 24) +
620 ((value & 0xff00) << 8) +
621 ((value & 0xff0000) >> 8) +
622 ((value & 0xff000000) >> 24);
623 } else {
624 value = ((value & 0xff) << 56) +
625 ((value & 0xff00) << 40) +
626 ((value & 0xff0000) << 24) +
627 ((value & 0xff000000ULL) << 8) +
628 ((value & 0xff00000000ULL) >> 8) +
629 ((value & 0xff0000000000ULL) >> 24) +
630 ((value & 0xff000000000000ULL) >> 40) +
631 ((value & 0xff00000000000000ULL) >> 56);
632 }
633 }
634 snprintf(r + strlen(r), maxlen - strlen(r), format, (uint64_t)value);
635 }
636
637
638 /*
639 * ppc_cpu_gdb_stub():
640 *
641 * Execute a "remote GDB" command. Returns a newly allocated response string
642 * on success, NULL on failure.
643 */
644 char *ppc_cpu_gdb_stub(struct cpu *cpu, char *cmd)
645 {
646 if (strcmp(cmd, "g") == 0) {
647 int i;
648 char *r;
649 size_t wlen = cpu->is_32bit?
650 sizeof(uint32_t) : sizeof(uint64_t);
651 size_t len = 1 + 76 * wlen;
652 r = malloc(len);
653 if (r == NULL) {
654 fprintf(stderr, "out of memory\n");
655 exit(1);
656 }
657 r[0] = '\0';
658 for (i=0; i<128; i++)
659 add_response_word(cpu, r, i, len, wlen);
660 return r;
661 }
662
663 if (cmd[0] == 'p') {
664 int regnr = strtol(cmd + 1, NULL, 16);
665 size_t wlen = cpu->is_32bit?
666 sizeof(uint32_t) : sizeof(uint64_t);
667 size_t len = 2 * wlen + 1;
668 char *r = malloc(len);
669 r[0] = '\0';
670 if (regnr >= 0 && regnr <= 31) {
671 add_response_word(cpu, r,
672 cpu->cd.ppc.gpr[regnr], len, wlen);
673 } else if (regnr == 0x40) {
674 add_response_word(cpu, r, cpu->pc, len, wlen);
675 } else if (regnr == 0x42) {
676 add_response_word(cpu, r, cpu->cd.ppc.cr, len, wlen);
677 } else if (regnr == 0x43) {
678 add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_LR],
679 len, wlen);
680 } else if (regnr == 0x44) {
681 add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_CTR],
682 len, wlen);
683 } else if (regnr == 0x45) {
684 add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_XER],
685 len, wlen);
686 } else {
687 /* Unimplemented: */
688 add_response_word(cpu, r, 0xcc000 + regnr, len, wlen);
689 }
690 return r;
691 }
692
693 fatal("ppc_cpu_gdb_stub(): TODO\n");
694 return NULL;
695 }
696
697
698 /*
699 * ppc_cpu_interrupt():
700 *
701 * 0..31 are used as BeBox interrupt numbers, 32..47 = ISA,
702 * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
703 *
704 * TODO: don't hardcode to BeBox!
705 */
706 int ppc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
707 {
708 /* fatal("ppc_cpu_interrupt(): 0x%x\n", (int)irq_nr); */
709 if (irq_nr <= 64) {
710 if (cpu->machine->md_interrupt != NULL)
711 cpu->machine->md_interrupt(
712 cpu->machine, cpu, irq_nr, 1);
713 else
714 fatal("ppc_cpu_interrupt(): md_interrupt == NULL\n");
715 } else {
716 /* Assert PPC IRQ: */
717 cpu->cd.ppc.irq_asserted = 1;
718 }
719 return 1;
720 }
721
722
723 /*
724 * ppc_cpu_interrupt_ack():
725 */
726 int ppc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
727 {
728 if (irq_nr <= 64) {
729 if (cpu->machine->md_interrupt != NULL)
730 cpu->machine->md_interrupt(cpu->machine,
731 cpu, irq_nr, 0);
732 } else {
733 /* De-assert PPC IRQ: */
734 cpu->cd.ppc.irq_asserted = 0;
735 }
736 return 1;
737 }
738
739
740 /*
741 * ppc_cpu_disassemble_instr():
742 *
743 * Convert an instruction word into human readable format, for instruction
744 * tracing.
745 *
746 * If running is 1, cpu->pc should be the address of the instruction.
747 *
748 * If running is 0, things that depend on the runtime environment (eg.
749 * register contents) will not be shown, and addr will be used instead of
750 * cpu->pc for relative addresses.
751 */
752 int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
753 int running, uint64_t dumpaddr)
754 {
755 int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
756 int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
757 int bfa, to, load, wlen, no_rb = 0;
758 uint64_t offset, addr;
759 uint32_t iword;
760 char *symbol, *mnem = "ERROR";
761 int power = cpu->cd.ppc.mode == MODE_POWER;
762
763 if (running)
764 dumpaddr = cpu->pc;
765
766 symbol = get_symbol_name(&cpu->machine->symbol_context,
767 dumpaddr, &offset);
768 if (symbol != NULL && offset==0)
769 debug("<%s>\n", symbol);
770
771 if (cpu->machine->ncpus > 1 && running)
772 debug("cpu%i: ", cpu->cpu_id);
773
774 if (cpu->cd.ppc.bits == 32)
775 debug("%08x", (int)dumpaddr);
776 else
777 debug("%016llx", (long long)dumpaddr);
778
779 /* NOTE: Fixed to big-endian. */
780 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
781 + instr[3];
782
783 debug(": %08x\t", iword);
784
785 /*
786 * Decode the instruction:
787 */
788
789 hi6 = iword >> 26;
790
791 switch (hi6) {
792 case 0x4:
793 debug("ALTIVEC TODO");
794 /* vxor etc */
795 break;
796 case PPC_HI6_MULLI:
797 case PPC_HI6_SUBFIC:
798 rt = (iword >> 21) & 31;
799 ra = (iword >> 16) & 31;
800 imm = (int16_t)(iword & 0xffff);
801 switch (hi6) {
802 case PPC_HI6_MULLI:
803 mnem = power? "muli":"mulli";
804 break;
805 case PPC_HI6_SUBFIC:
806 mnem = power? "sfi":"subfic";
807 break;
808 }
809 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
810 break;
811 case PPC_HI6_CMPLI:
812 case PPC_HI6_CMPI:
813 bf = (iword >> 23) & 7;
814 l_bit = (iword >> 21) & 1;
815 ra = (iword >> 16) & 31;
816 if (hi6 == PPC_HI6_CMPLI) {
817 imm = iword & 0xffff;
818 mnem = "cmpl";
819 } else {
820 imm = (int16_t)(iword & 0xffff);
821 mnem = "cmp";
822 }
823 debug("%s%si\t", mnem, l_bit? "d" : "w");
824 if (bf != 0)
825 debug("cr%i,", bf);
826 debug("r%i,%i", ra, imm);
827 break;
828 case PPC_HI6_ADDIC:
829 case PPC_HI6_ADDIC_DOT:
830 rt = (iword >> 21) & 31;
831 ra = (iword >> 16) & 31;
832 rc = hi6 == PPC_HI6_ADDIC_DOT;
833 imm = (int16_t)(iword & 0xffff);
834 mnem = power? "ai":"addic";
835 if (imm < 0 && !power) {
836 mnem = "subic";
837 imm = -imm;
838 }
839 debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
840 break;
841 case PPC_HI6_ADDI:
842 rt = (iword >> 21) & 31;
843 ra = (iword >> 16) & 31;
844 imm = (int16_t)(iword & 0xffff);
845 if (ra == 0)
846 debug("li\tr%i,%i", rt, imm);
847 else {
848 mnem = power? "cal":"addi";
849 if (imm < 0 && !power) {
850 mnem = "subi";
851 imm = -imm;
852 }
853 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
854 }
855 break;
856 case PPC_HI6_ADDIS:
857 rt = (iword >> 21) & 31;
858 ra = (iword >> 16) & 31;
859 imm = (int16_t)(iword & 0xffff);
860 if (ra == 0)
861 debug("lis\tr%i,%i", rt, imm);
862 else
863 debug("%s\tr%i,r%i,%i",
864 power? "cau":"addis", rt, ra, imm);
865 break;
866 case PPC_HI6_BC:
867 aa_bit = (iword & 2) >> 1;
868 lk_bit = iword & 1;
869 bo = (iword >> 21) & 31;
870 bi = (iword >> 16) & 31;
871 /* Sign-extend addr: */
872 addr = (int64_t)(int16_t)(iword & 0xfffc);
873 debug("bc");
874 if (lk_bit)
875 debug("l");
876 if (aa_bit)
877 debug("a");
878 else
879 addr += dumpaddr;
880 debug("\t%i,%i,", bo, bi);
881 if (cpu->cd.ppc.bits == 32)
882 addr &= 0xffffffff;
883 if (cpu->cd.ppc.bits == 32)
884 debug("0x%x", (int)addr);
885 else
886 debug("0x%llx", (long long)addr);
887 symbol = get_symbol_name(&cpu->machine->symbol_context,
888 addr, &offset);
889 if (symbol != NULL)
890 debug("\t<%s>", symbol);
891 break;
892 case PPC_HI6_SC:
893 lev = (iword >> 5) & 0x7f;
894 debug("sc");
895 if (lev != 0) {
896 debug("\t%i", lev);
897 if (lev > 1)
898 debug(" (WARNING! reserved value)");
899 }
900 break;
901 case PPC_HI6_B:
902 aa_bit = (iword & 2) >> 1;
903 lk_bit = iword & 1;
904 /* Sign-extend addr: */
905 addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
906 addr = (int64_t)addr >> 6;
907 debug("b");
908 if (lk_bit)
909 debug("l");
910 if (aa_bit)
911 debug("a");
912 else
913 addr += dumpaddr;
914 if (cpu->cd.ppc.bits == 32)
915 addr &= 0xffffffff;
916 if (cpu->cd.ppc.bits == 32)
917 debug("\t0x%x", (int)addr);
918 else
919 debug("\t0x%llx", (long long)addr);
920 symbol = get_symbol_name(&cpu->machine->symbol_context,
921 addr, &offset);
922 if (symbol != NULL)
923 debug("\t<%s>", symbol);
924 break;
925 case PPC_HI6_19:
926 xo = (iword >> 1) & 1023;
927 switch (xo) {
928 case PPC_19_MCRF:
929 bf = (iword >> 23) & 7;
930 bfa = (iword >> 18) & 7;
931 debug("mcrf\tcr%i,cr%i", bf, bfa);
932 break;
933 case PPC_19_RFI:
934 debug("rfi");
935 break;
936 case PPC_19_RFID:
937 debug("rfid");
938 break;
939 case PPC_19_RFSVC:
940 debug("rfsvc%s", power?"":"\t(INVALID for PowerPC)");
941 break;
942 case PPC_19_BCLR:
943 case PPC_19_BCCTR:
944 bo = (iword >> 21) & 31;
945 bi = (iword >> 16) & 31;
946 bh = (iword >> 11) & 3;
947 lk_bit = iword & 1;
948 switch (xo) {
949 case PPC_19_BCLR:
950 mnem = power? "bcr" : "bclr"; break;
951 case PPC_19_BCCTR:
952 mnem = power? "bcc" : "bcctr"; break;
953 }
954 debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
955 bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
956 bo, bi, bh);
957 break;
958 case PPC_19_ISYNC:
959 debug("%s", power? "ics" : "isync");
960 break;
961 case PPC_19_CRAND:
962 case PPC_19_CRXOR:
963 case PPC_19_CROR:
964 case PPC_19_CRNAND:
965 case PPC_19_CRNOR:
966 case PPC_19_CRANDC:
967 case PPC_19_CREQV:
968 case PPC_19_CRORC:
969 bt = (iword >> 21) & 31;
970 ba = (iword >> 16) & 31;
971 bb = (iword >> 11) & 31;
972 switch (xo) {
973 case PPC_19_CRAND: mnem = "crand"; break;
974 case PPC_19_CRXOR: mnem = "crxor"; break;
975 case PPC_19_CROR: mnem = "cror"; break;
976 case PPC_19_CRNAND: mnem = "crnand"; break;
977 case PPC_19_CRNOR: mnem = "crnor"; break;
978 case PPC_19_CRANDC: mnem = "crandc"; break;
979 case PPC_19_CREQV: mnem = "creqv"; break;
980 case PPC_19_CRORC: mnem = "crorc"; break;
981 }
982 debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
983 break;
984 default:
985 debug("unimplemented hi6_19, xo = 0x%x", xo);
986 }
987 break;
988 case PPC_HI6_RLWNM:
989 case PPC_HI6_RLWIMI:
990 case PPC_HI6_RLWINM:
991 rs = (iword >> 21) & 31;
992 ra = (iword >> 16) & 31;
993 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
994 mb = (iword >> 6) & 31;
995 me = (iword >> 1) & 31;
996 rc = iword & 1;
997 switch (hi6) {
998 case PPC_HI6_RLWNM:
999 mnem = power? "rlnm" : "rlwnm"; break;
1000 case PPC_HI6_RLWIMI:
1001 mnem = power? "rlimi" : "rlwimi"; break;
1002 case PPC_HI6_RLWINM:
1003 mnem = power? "rlinm" : "rlwinm"; break;
1004 }
1005 debug("%s%s\tr%i,r%i,%s%i,%i,%i",
1006 mnem, rc?".":"", ra, rs,
1007 hi6 == PPC_HI6_RLWNM? "r" : "",
1008 sh, mb, me);
1009 break;
1010 case PPC_HI6_ORI:
1011 case PPC_HI6_ORIS:
1012 case PPC_HI6_XORI:
1013 case PPC_HI6_XORIS:
1014 case PPC_HI6_ANDI_DOT:
1015 case PPC_HI6_ANDIS_DOT:
1016 rs = (iword >> 21) & 31;
1017 ra = (iword >> 16) & 31;
1018 imm = iword & 0xffff;
1019 switch (hi6) {
1020 case PPC_HI6_ORI:
1021 mnem = power? "oril":"ori";
1022 break;
1023 case PPC_HI6_ORIS:
1024 mnem = power? "oriu":"oris";
1025 break;
1026 case PPC_HI6_XORI:
1027 mnem = power? "xoril":"xori";
1028 break;
1029 case PPC_HI6_XORIS:
1030 mnem = power? "xoriu":"xoris";
1031 break;
1032 case PPC_HI6_ANDI_DOT:
1033 mnem = power? "andil.":"andi.";
1034 break;
1035 case PPC_HI6_ANDIS_DOT:
1036 mnem = power? "andiu.":"andis.";
1037 break;
1038 }
1039 if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
1040 debug("nop");
1041 else
1042 debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
1043 break;
1044 case PPC_HI6_30:
1045 xo = (iword >> 2) & 7;
1046 switch (xo) {
1047 case PPC_30_RLDICL:
1048 case PPC_30_RLDICR:
1049 case PPC_30_RLDIMI: /* mb, not me */
1050 mnem = NULL;
1051 switch (xo) {
1052 case PPC_30_RLDICL: mnem = "rldicl"; break;
1053 case PPC_30_RLDICR: mnem = "rldicr"; break;
1054 case PPC_30_RLDIMI: mnem = "rldimi"; break;
1055 }
1056 rs = (iword >> 21) & 31;
1057 ra = (iword >> 16) & 31;
1058 sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
1059 me = ((iword >> 6) & 31) | (iword & 0x20);
1060 rc = iword & 1;
1061 debug("%s%s\tr%i,r%i,%i,%i",
1062 mnem, rc?".":"", ra, rs, sh, me);
1063 break;
1064 default:
1065 debug("unimplemented hi6_30, xo = 0x%x", xo);
1066 }
1067 break;
1068 case PPC_HI6_31:
1069 xo = (iword >> 1) & 1023;
1070 switch (xo) {
1071
1072 case PPC_31_CMP:
1073 case PPC_31_CMPL:
1074 bf = (iword >> 23) & 7;
1075 l_bit = (iword >> 21) & 1;
1076 ra = (iword >> 16) & 31;
1077 rb = (iword >> 11) & 31;
1078 if (xo == PPC_31_CMPL)
1079 mnem = "cmpl";
1080 else
1081 mnem = "cmp";
1082 debug("%s%s\t", mnem, l_bit? "d" : "w");
1083 if (bf != 0)
1084 debug("cr%i,", bf);
1085 debug("r%i,r%i", ra, rb);
1086 break;
1087 case PPC_31_MFCR:
1088 rt = (iword >> 21) & 31;
1089 debug("mfcr\tr%i", rt);
1090 break;
1091 case PPC_31_MFMSR:
1092 rt = (iword >> 21) & 31;
1093 debug("mfmsr\tr%i", rt);
1094 break;
1095 case PPC_31_MTCRF:
1096 rs = (iword >> 21) & 31;
1097 mb = (iword >> 12) & 255; /* actually fxm, not mb */
1098 debug("mtcrf\t%i,r%i", mb, rs);
1099 break;
1100 case PPC_31_MTMSR:
1101 rs = (iword >> 21) & 31;
1102 l_bit = (iword >> 16) & 1;
1103 debug("mtmsr\tr%i", rs);
1104 if (l_bit)
1105 debug(",%i", l_bit);
1106 break;
1107 case PPC_31_TW:
1108 case PPC_31_TD:
1109 to = (iword >> 21) & 31;
1110 ra = (iword >> 16) & 31;
1111 rb = (iword >> 11) & 31;
1112 switch (xo) {
1113 case PPC_31_TW: mnem = power? "t" : "tw"; break;
1114 case PPC_31_TD: mnem = "td"; break;
1115 }
1116 debug("%s\t%i,r%i,r%i", mnem, to, ra, rb);
1117 break;
1118 case PPC_31_LWARX:
1119 case PPC_31_LDARX:
1120 case PPC_31_LBZX:
1121 case PPC_31_LBZUX:
1122 case PPC_31_LHAX:
1123 case PPC_31_LHAUX:
1124 case PPC_31_LHZX:
1125 case PPC_31_LHZUX:
1126 case PPC_31_LWZX:
1127 case PPC_31_LWZUX:
1128 case PPC_31_LHBRX:
1129 case PPC_31_LWBRX:
1130 case PPC_31_LFDX:
1131 case PPC_31_LFSX:
1132 case PPC_31_STWCX_DOT:
1133 case PPC_31_STDCX_DOT:
1134 case PPC_31_STBX:
1135 case PPC_31_STBUX:
1136 case PPC_31_STHX:
1137 case PPC_31_STHUX:
1138 case PPC_31_STWX:
1139 case PPC_31_STWUX:
1140 case PPC_31_STDX:
1141 case PPC_31_STDUX:
1142 case PPC_31_STHBRX:
1143 case PPC_31_STWBRX:
1144 case PPC_31_STFDX:
1145 case PPC_31_STFSX:
1146 /* rs for stores, rt for loads, actually */
1147 load = 0; wlen = 0; fpreg = 0;
1148 rs = (iword >> 21) & 31;
1149 ra = (iword >> 16) & 31;
1150 rb = (iword >> 11) & 31;
1151 switch (xo) {
1152 case PPC_31_LWARX: wlen=4;load=1; mnem = "lwarx"; break;
1153 case PPC_31_LDARX: wlen=8;load=1; mnem = "ldarx"; break;
1154 case PPC_31_LBZX: wlen=1;load=1; mnem = "lbzx"; break;
1155 case PPC_31_LBZUX: wlen=1;load=1; mnem = "lbzux"; break;
1156 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1157 case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1158 case PPC_31_LHZX: wlen=2;load=1; mnem = "lhzx"; break;
1159 case PPC_31_LHZUX: wlen=2;load=1; mnem = "lhzux"; break;
1160 case PPC_31_LWZX: wlen = 4; load = 1;
1161 mnem = power? "lx" : "lwzx";
1162 break;
1163 case PPC_31_LWZUX: wlen = 4; load = 1;
1164 mnem = power? "lux":"lwzux";
1165 break;
1166 case PPC_31_LFDX: fpreg = 1; wlen = 8; load = 1;
1167 mnem = "lfdx"; break;
1168 case PPC_31_LFSX: fpreg = 1; wlen = 4; load = 1;
1169 mnem = "lfsx"; break;
1170 case PPC_31_STWCX_DOT: wlen=4; mnem = "stwcx."; break;
1171 case PPC_31_STDCX_DOT: wlen=8; mnem = "stdcx."; break;
1172 case PPC_31_STBX: wlen=1; mnem = "stbx"; break;
1173 case PPC_31_STBUX: wlen=1; mnem = "stbux"; break;
1174 case PPC_31_STHX: wlen=2; mnem = "sthx"; break;
1175 case PPC_31_STHUX: wlen=2; mnem = "sthux"; break;
1176 case PPC_31_STWX:
1177 wlen = 4; mnem = power? "stx" : "stwx";
1178 break;
1179 case PPC_31_STWUX:
1180 wlen = 4; mnem = power? "stux" : "stwux";
1181 break;
1182 case PPC_31_STDX: wlen = 8; mnem = "stdx"; break;
1183 case PPC_31_STDUX: wlen = 8; mnem = "stdux"; break;
1184 case PPC_31_LHBRX: wlen = 2; mnem = "lhbrx"; break;
1185 case PPC_31_LWBRX: wlen = 4; mnem = power?
1186 "lbrx" : "lwbrx"; break;
1187 case PPC_31_STHBRX: wlen = 2; mnem = "sthbrx"; break;
1188 case PPC_31_STWBRX: wlen = 4; mnem = power?
1189 "stbrx" : "stwbrx"; break;
1190 case PPC_31_STFDX: fpreg = 1; wlen = 8;
1191 mnem = "stfdx"; break;
1192 case PPC_31_STFSX: fpreg = 1; wlen = 4;
1193 mnem = "stfsx"; break;
1194 }
1195 debug("%s\t%s%i,r%i,r%i", mnem,
1196 fpreg? "f" : "r", rs, ra, rb);
1197 if (!running)
1198 break;
1199 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1200 cpu->cd.ppc.gpr[rb];
1201 if (cpu->cd.ppc.bits == 32)
1202 addr &= 0xffffffff;
1203 symbol = get_symbol_name(&cpu->machine->symbol_context,
1204 addr, &offset);
1205 if (symbol != NULL)
1206 debug(" \t<%s", symbol);
1207 else
1208 debug(" \t<0x%llx", (long long)addr);
1209 if (wlen > 0 && !fpreg /* && !reverse */) {
1210 /* TODO */
1211 }
1212 debug(">");
1213 break;
1214 case PPC_31_NEG:
1215 case PPC_31_NEGO:
1216 rt = (iword >> 21) & 31;
1217 ra = (iword >> 16) & 31;
1218 oe_bit = (iword >> 10) & 1;
1219 rc = iword & 1;
1220 switch (xo) {
1221 case PPC_31_NEG: mnem = "neg"; break;
1222 case PPC_31_NEGO: mnem = "nego"; break;
1223 }
1224 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1225 break;
1226 case PPC_31_WRTEEI:
1227 debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1228 break;
1229 case PPC_31_MTMSRD:
1230 /* TODO: Just a guess based on MTMSR */
1231 rs = (iword >> 21) & 31;
1232 l_bit = (iword >> 16) & 1;
1233 debug("mtmsrd\tr%i", rs);
1234 if (l_bit)
1235 debug(",%i", l_bit);
1236 break;
1237 case PPC_31_ADDZE:
1238 case PPC_31_ADDZEO:
1239 rt = (iword >> 21) & 31;
1240 ra = (iword >> 16) & 31;
1241 oe_bit = (iword >> 10) & 1;
1242 rc = iword & 1;
1243 switch (xo) {
1244 case PPC_31_ADDZE:
1245 mnem = power? "aze" : "addze";
1246 break;
1247 case PPC_31_ADDZEO:
1248 mnem = power? "azeo" : "addzeo";
1249 break;
1250 }
1251 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1252 break;
1253 case PPC_31_MTSR:
1254 case PPC_31_MFSR:
1255 /* Move to/from segment register */
1256 rt = (iword >> 21) & 31;
1257 ra = (iword >> 16) & 15; /* actually: sr */
1258 switch (xo) {
1259 case PPC_31_MTSR: mnem = "mtsr"; break;
1260 case PPC_31_MFSR: mnem = "mfsr"; break;
1261 }
1262 debug("%s\tr%i,%i", mnem, rt, ra);
1263 break;
1264 case PPC_31_MTSRIN:
1265 case PPC_31_MFSRIN:
1266 /* Move to/from segment register indirect */
1267 rt = (iword >> 21) & 31;
1268 rb = (iword >> 11) & 31;
1269 switch (xo) {
1270 case PPC_31_MTSRIN: mnem = "mtsrin"; break;
1271 case PPC_31_MFSRIN: mnem = "mfsrin"; break;
1272 }
1273 debug("%s\tr%i,r%i", mnem, rt, rb);
1274 break;
1275 case PPC_31_ADDC:
1276 case PPC_31_ADDCO:
1277 case PPC_31_ADDE:
1278 case PPC_31_ADDEO:
1279 case PPC_31_ADDME:
1280 case PPC_31_ADDMEO:
1281 case PPC_31_ADD:
1282 case PPC_31_ADDO:
1283 case PPC_31_MULHW:
1284 case PPC_31_MULHWU:
1285 case PPC_31_MULLW:
1286 case PPC_31_MULLWO:
1287 case PPC_31_SUBF:
1288 case PPC_31_SUBFO:
1289 case PPC_31_SUBFC:
1290 case PPC_31_SUBFCO:
1291 case PPC_31_SUBFE:
1292 case PPC_31_SUBFEO:
1293 case PPC_31_SUBFME:
1294 case PPC_31_SUBFMEO:
1295 case PPC_31_SUBFZE:
1296 case PPC_31_SUBFZEO:
1297 rt = (iword >> 21) & 31;
1298 ra = (iword >> 16) & 31;
1299 rb = (iword >> 11) & 31;
1300 oe_bit = (iword >> 10) & 1;
1301 rc = iword & 1;
1302 switch (xo) {
1303 case PPC_31_ADDC:
1304 mnem = power? "a" : "addc";
1305 break;
1306 case PPC_31_ADDCO:
1307 mnem = power? "ao" : "addco";
1308 break;
1309 case PPC_31_ADDE:
1310 mnem = power? "ae" : "adde";
1311 break;
1312 case PPC_31_ADDEO:
1313 mnem = power? "aeo" : "addeo";
1314 break;
1315 case PPC_31_ADDME:
1316 mnem = power? "ame" : "addme";
1317 no_rb = 1;
1318 break;
1319 case PPC_31_ADDMEO:
1320 mnem = power? "ameo" : "addmeo";
1321 no_rb = 1;
1322 break;
1323 case PPC_31_ADD:
1324 mnem = power? "cax" : "add";
1325 break;
1326 case PPC_31_ADDO:
1327 mnem = power? "caxo" : "addo";
1328 break;
1329 case PPC_31_MULHW: mnem = "mulhw"; break;
1330 case PPC_31_MULHWU: mnem = "mulhwu"; break;
1331 case PPC_31_MULLW:
1332 mnem = power? "muls" : "mullw";
1333 break;
1334 case PPC_31_MULLWO:
1335 mnem = power? "mulso" : "mullwo";
1336 break;
1337 case PPC_31_SUBF: mnem = "subf"; break;
1338 case PPC_31_SUBFO: mnem = "subfo"; break;
1339 case PPC_31_SUBFC:
1340 mnem = power? "sf" : "subfc"; break;
1341 case PPC_31_SUBFCO:
1342 mnem = power? "sfo" : "subfco"; break;
1343 case PPC_31_SUBFE:
1344 mnem = power? "sfe" : "subfe"; break;
1345 case PPC_31_SUBFEO:
1346 mnem = power? "sfeo" : "subfeo"; break;
1347 case PPC_31_SUBFME:
1348 mnem = power? "sfme" : "subfme"; break;
1349 case PPC_31_SUBFMEO:
1350 mnem = power? "sfmeo" : "subfmeo"; break;
1351 case PPC_31_SUBFZE:
1352 mnem = power? "sfze" : "subfze";
1353 no_rb = 1;
1354 break;
1355 case PPC_31_SUBFZEO:
1356 mnem = power? "sfzeo" : "subfzeo";
1357 no_rb = 1;
1358 break;
1359 }
1360 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1361 if (!no_rb)
1362 debug(",r%i", rb);
1363 break;
1364 case PPC_31_MFSPR:
1365 rt = (iword >> 21) & 31;
1366 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1367 switch (spr) {
1368 /* Some very common ones: */
1369 case 8: debug("mflr\tr%i", rt); break;
1370 case 9: debug("mfctr\tr%i", rt); break;
1371 default:debug("mfspr\tr%i,spr%i", rt, spr);
1372 }
1373 if (spr == 8 || spr == 9)
1374 debug("\t");
1375 debug("\t<%s%s", running? "read from " : "",
1376 ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1377 if (running) {
1378 if (cpu->cd.ppc.bits == 32)
1379 debug(": 0x%x", (int)
1380 cpu->cd.ppc.spr[spr]);
1381 else
1382 debug(": 0x%llx", (long long)
1383 cpu->cd.ppc.spr[spr]);
1384 }
1385 debug(">");
1386 break;
1387 case PPC_31_TLBIA:
1388 debug("tlbia");
1389 break;
1390 case PPC_31_SLBIA:
1391 debug("slbia");
1392 break;
1393 case PPC_31_TLBLD:
1394 case PPC_31_TLBLI:
1395 rb = (iword >> 11) & 31;
1396 debug("tlbl%s\tr%i", xo == PPC_31_TLBLD? "d" : "i", rb);
1397 break;
1398 case PPC_31_TLBIE:
1399 /* TODO: what is ra? The IBM online docs didn't say */
1400 ra = 0;
1401 rb = (iword >> 11) & 31;
1402 if (power)
1403 debug("tlbi\tr%i,r%i", ra, rb);
1404 else
1405 debug("tlbie\tr%i", rb);
1406 break;
1407 case PPC_31_TLBSX_DOT:
1408 rs = (iword >> 21) & 31;
1409 ra = (iword >> 16) & 31;
1410 rb = (iword >> 11) & 31;
1411 debug("tlbsx.\tr%i,r%i,r%i", rs, ra, rb);
1412 break;
1413 case PPC_31_TLBSYNC:
1414 debug("tlbsync");
1415 break;
1416 case PPC_31_MFTB:
1417 rt = (iword >> 21) & 31;
1418 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1419 debug("mftb%s\tr%i", spr==268? "" :
1420 (spr==269? "u" : "?"), rt);
1421 break;
1422 case PPC_31_CNTLZW:
1423 rs = (iword >> 21) & 31;
1424 ra = (iword >> 16) & 31;
1425 rc = iword & 1;
1426 mnem = power? "cntlz" : "cntlzw";
1427 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1428 break;
1429 case PPC_31_CLF: /* POWER only */
1430 case PPC_31_CLI: /* POWER only */
1431 case PPC_31_DCLST: /* POWER only */
1432 case PPC_31_DCBF: /* PowerPC only */
1433 case PPC_31_DCBI: /* PowerPC only */
1434 case PPC_31_DCBST: /* PowerPC only */
1435 case PPC_31_DCBTST: /* PowerPC only */
1436 case PPC_31_DCBT: /* PowerPC only */
1437 case PPC_31_ICBI: /* PowerPC only */
1438 case PPC_31_DCBZ: /* POWER/PowerPC */
1439 ra = (iword >> 16) & 31;
1440 rb = (iword >> 11) & 31;
1441 switch (xo) {
1442 case PPC_31_CLF: mnem = "clf"; break;
1443 case PPC_31_CLI: mnem = "cli"; break;
1444 case PPC_31_DCLST: mnem = "dclst"; break;
1445 case PPC_31_DCBF: mnem = "dcbf"; break;
1446 case PPC_31_DCBI: mnem = "dcbi"; break;
1447 case PPC_31_DCBST: mnem = "dcbst"; break;
1448 case PPC_31_DCBTST:mnem = "dcbtst"; break;
1449 case PPC_31_DCBT: mnem = "dcbt"; break;
1450 case PPC_31_ICBI: mnem = "icbi"; break;
1451 case PPC_31_DCBZ: mnem = power ?
1452 "dclz" : "dcbz"; break;
1453 }
1454 debug("%s\tr%i,r%i", mnem, ra, rb);
1455 break;
1456 case PPC_31_SLW:
1457 case PPC_31_SLD:
1458 case PPC_31_SRAW:
1459 case PPC_31_SRW:
1460 case PPC_31_AND:
1461 case PPC_31_ANDC:
1462 case PPC_31_NOR:
1463 case PPC_31_EQV:
1464 case PPC_31_OR:
1465 case PPC_31_ORC:
1466 case PPC_31_XOR:
1467 case PPC_31_NAND:
1468 rs = (iword >> 21) & 31;
1469 ra = (iword >> 16) & 31;
1470 rb = (iword >> 11) & 31;
1471 rc = iword & 1;
1472 if (rs == rb && xo == PPC_31_OR)
1473 debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
1474 else {
1475 switch (xo) {
1476 case PPC_31_SLW: mnem =
1477 power? "sl" : "slw"; break;
1478 case PPC_31_SLD: mnem = "sld"; break;
1479 case PPC_31_SRAW: mnem =
1480 power? "sra" : "sraw"; break;
1481 case PPC_31_SRW: mnem =
1482 power? "sr" : "srw"; break;
1483 case PPC_31_AND: mnem = "and"; break;
1484 case PPC_31_NAND: mnem = "nand"; break;
1485 case PPC_31_ANDC: mnem = "andc"; break;
1486 case PPC_31_NOR: mnem = "nor"; break;
1487 case PPC_31_EQV: mnem = "eqv"; break;
1488 case PPC_31_OR: mnem = "or"; break;
1489 case PPC_31_ORC: mnem = "orc"; break;
1490 case PPC_31_XOR: mnem = "xor"; break;
1491 }
1492 debug("%s%s\tr%i,r%i,r%i", mnem,
1493 rc? "." : "", ra, rs, rb);
1494 }
1495 break;
1496 case PPC_31_DCCCI:
1497 ra = (iword >> 16) & 31;
1498 rb = (iword >> 11) & 31;
1499 debug("dccci\tr%i,r%i", ra, rb);
1500 break;
1501 case PPC_31_ICCCI:
1502 ra = (iword >> 16) & 31;
1503 rb = (iword >> 11) & 31;
1504 debug("iccci\tr%i,r%i", ra, rb);
1505 break;
1506 case PPC_31_DIVW:
1507 case PPC_31_DIVWO:
1508 case PPC_31_DIVWU:
1509 case PPC_31_DIVWUO:
1510 rt = (iword >> 21) & 31;
1511 ra = (iword >> 16) & 31;
1512 rb = (iword >> 11) & 31;
1513 oe_bit = (iword >> 10) & 1;
1514 rc = iword & 1;
1515 switch (xo) {
1516 case PPC_31_DIVWU: mnem = "divwu"; break;
1517 case PPC_31_DIVWUO: mnem = "divwuo"; break;
1518 case PPC_31_DIVW: mnem = "divw"; break;
1519 case PPC_31_DIVWO: mnem = "divwo"; break;
1520 }
1521 debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1522 rt, ra, rb);
1523 break;
1524 case PPC_31_MTSPR:
1525 rs = (iword >> 21) & 31;
1526 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1527 switch (spr) {
1528 /* Some very common ones: */
1529 case 8: debug("mtlr\tr%i", rs); break;
1530 case 9: debug("mtctr\tr%i", rs); break;
1531 default:debug("mtspr\tspr%i,r%i", spr, rs);
1532 }
1533 if (spr == 8 || spr == 9)
1534 debug("\t");
1535 debug("\t<%s%s", running? "write to " : "",
1536 ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1537 if (running) {
1538 if (cpu->cd.ppc.bits == 32)
1539 debug(": 0x%x", (int)
1540 cpu->cd.ppc.gpr[rs]);
1541 else
1542 debug(": 0x%llx", (long long)
1543 cpu->cd.ppc.gpr[rs]);
1544 }
1545 debug(">");
1546 break;
1547 case PPC_31_SYNC:
1548 debug("%s", power? "dcs" : "sync");
1549 break;
1550 case PPC_31_LSWI:
1551 case PPC_31_STSWI:
1552 rs = (iword >> 21) & 31; /* lwsi uses rt */
1553 ra = (iword >> 16) & 31;
1554 nb = (iword >> 11) & 31;
1555 switch (xo) {
1556 case PPC_31_LSWI:
1557 mnem = power? "lsi" : "lswi"; break;
1558 case PPC_31_STSWI:
1559 mnem = power? "stsi" : "stswi"; break;
1560 }
1561 debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb);
1562 break;
1563 case PPC_31_SRAWI:
1564 rs = (iword >> 21) & 31;
1565 ra = (iword >> 16) & 31;
1566 sh = (iword >> 11) & 31;
1567 rc = iword & 1;
1568 mnem = power? "srai" : "srawi";
1569 debug("%s%s\tr%i,r%i,%i", mnem,
1570 rc? "." : "", ra, rs, sh);
1571 break;
1572 case PPC_31_DSSALL:
1573 debug("dssall");
1574 break;
1575 case PPC_31_EIEIO:
1576 debug("%s", power? "eieio?" : "eieio");
1577 break;
1578 case PPC_31_EXTSB:
1579 case PPC_31_EXTSH:
1580 case PPC_31_EXTSW:
1581 rs = (iword >> 21) & 31;
1582 ra = (iword >> 16) & 31;
1583 rc = iword & 1;
1584 switch (xo) {
1585 case PPC_31_EXTSB:
1586 mnem = power? "exts" : "extsb";
1587 break;
1588 case PPC_31_EXTSH:
1589 mnem = "extsh";
1590 break;
1591 case PPC_31_EXTSW:
1592 mnem = "extsw";
1593 break;
1594 }
1595 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1596 break;
1597 case PPC_31_LVX:
1598 case PPC_31_LVXL:
1599 case PPC_31_STVX:
1600 case PPC_31_STVXL:
1601 rs = (iword >> 21) & 31; /* vs for stores, */
1602 ra = (iword >> 16) & 31; /* rs=vl for loads */
1603 rb = (iword >> 11) & 31;
1604 rc = iword & 1;
1605 switch (xo) {
1606 case PPC_31_LVX: mnem = "lvx"; break;
1607 case PPC_31_LVXL: mnem = "lvxl"; break;
1608 case PPC_31_STVX: mnem = "stvx"; break;
1609 case PPC_31_STVXL: mnem = "stvxl"; break;
1610 }
1611 debug("%s%s\tv%i,r%i,r%i", mnem, rc? "." : "",
1612 rs, ra, rb);
1613 break;
1614 default:
1615 debug("unimplemented hi6_31, xo = 0x%x", xo);
1616 }
1617 break;
1618 case PPC_HI6_LD:
1619 case PPC_HI6_LWZ:
1620 case PPC_HI6_LWZU:
1621 case PPC_HI6_LHZ:
1622 case PPC_HI6_LHZU:
1623 case PPC_HI6_LHA:
1624 case PPC_HI6_LHAU:
1625 case PPC_HI6_LBZ:
1626 case PPC_HI6_LBZU:
1627 case PPC_HI6_LFD:
1628 case PPC_HI6_LFS:
1629 case PPC_HI6_LMW:
1630 case PPC_HI6_STD:
1631 case PPC_HI6_STW:
1632 case PPC_HI6_STWU:
1633 case PPC_HI6_STH:
1634 case PPC_HI6_STHU:
1635 case PPC_HI6_STB:
1636 case PPC_HI6_STBU:
1637 case PPC_HI6_STMW:
1638 case PPC_HI6_STFD:
1639 case PPC_HI6_STFS:
1640 /* NOTE: Loads use rt, not rs, but are otherwise similar
1641 to stores */
1642 load = 0; wlen = 0;
1643 rs = (iword >> 21) & 31;
1644 ra = (iword >> 16) & 31;
1645 imm = (int16_t)(iword & 0xffff);
1646 fpreg = 0;
1647 switch (hi6) {
1648 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1649 case PPC_HI6_LWZ: load=1; wlen = 4;
1650 mnem = power? "l" : "lwz"; break;
1651 case PPC_HI6_LWZU: load=1; wlen = 4;
1652 mnem = power? "lu" : "lwzu"; break;
1653 case PPC_HI6_LHZ: load=1; wlen = 2;
1654 mnem = "lhz"; break;
1655 case PPC_HI6_LHZU: load=1; wlen = 2;
1656 mnem = "lhzu"; break;
1657 case PPC_HI6_LHA: load=2; wlen = 2;
1658 mnem = "lha"; break;
1659 case PPC_HI6_LHAU: load=2; wlen = 2;
1660 mnem = "lhau"; break;
1661 case PPC_HI6_LBZ: load=1; wlen = 1;
1662 mnem = "lbz"; break;
1663 case PPC_HI6_LBZU: load=1; wlen = 1;
1664 mnem = "lbzu"; break;
1665 case PPC_HI6_LFD: load=1; fpreg=1; wlen=8; mnem = "lfd"; break;
1666 case PPC_HI6_LFS: load=1; fpreg=1; wlen=4; mnem = "lfs"; break;
1667 case PPC_HI6_STD: wlen=8; mnem = "std"; break;
1668 case PPC_HI6_STW: wlen=4; mnem = power? "st" : "stw"; break;
1669 case PPC_HI6_STWU: wlen=4; mnem = power? "stu" : "stwu"; break;
1670 case PPC_HI6_STH: wlen=2; mnem = "sth"; break;
1671 case PPC_HI6_STHU: wlen=2; mnem = "sthu"; break;
1672 case PPC_HI6_STB: wlen=1; mnem = "stb"; break;
1673 case PPC_HI6_STBU: wlen=1; mnem = "stbu"; break;
1674 case PPC_HI6_LMW: load=1; mnem = power? "lm" : "lmw"; break;
1675 case PPC_HI6_STMW: mnem = power? "stm" : "stmw"; break;
1676 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1677 case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1678 }
1679 debug("%s\t", mnem);
1680 if (fpreg)
1681 debug("f");
1682 else
1683 debug("r");
1684 debug("%i,%i(r%i)", rs, imm, ra);
1685 if (!running)
1686 break;
1687 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) + imm;
1688 if (cpu->cd.ppc.bits == 32)
1689 addr &= 0xffffffff;
1690 symbol = get_symbol_name(&cpu->machine->symbol_context,
1691 addr, &offset);
1692 if (symbol != NULL)
1693 debug(" \t<%s", symbol);
1694 else
1695 debug(" \t<0x%llx", (long long)addr);
1696 if (wlen > 0 && load && wlen > 0) {
1697 unsigned char tw[8];
1698 uint64_t tdata = 0;
1699 int i, res = cpu->memory_rw(cpu, cpu->mem, addr, tw,
1700 wlen, MEM_READ, NO_EXCEPTIONS);
1701 if (res) {
1702 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1703 for (i=0; i<wlen; i++) {
1704 tdata <<= 8;
1705 tdata |= tw[wlen-1-i];
1706 }
1707 else
1708 for (i=0; i<wlen; i++) {
1709 tdata <<= 8;
1710 tdata |= tw[i];
1711 }
1712 debug(": ");
1713 if (wlen >= 4) {
1714 symbol = get_symbol_name(&cpu->machine->
1715 symbol_context, tdata, &offset);
1716 if (symbol != NULL)
1717 debug("%s", symbol);
1718 else
1719 debug("0x%llx",
1720 (long long)tdata);
1721 } else {
1722 /* TODO: if load==2, then this is
1723 a _signed_ load. */
1724 debug("0x%llx", (long long)tdata);
1725 }
1726 } else
1727 debug(": unreadable");
1728 }
1729 if (wlen > 0 && !load && wlen > 0) {
1730 int64_t tdata = 0;
1731 int i;
1732 for (i=0; i<wlen; i++)
1733 tdata |= (cpu->cd.ppc.gpr[rs] &
1734 ((uint64_t)0xff << (i*8)));
1735 debug(": ");
1736 if (wlen >= 4) {
1737 symbol = get_symbol_name(&cpu->machine->
1738 symbol_context, tdata, &offset);
1739 if (symbol != NULL)
1740 debug("%s", symbol);
1741 else
1742 debug("0x%llx", (long long)tdata);
1743 } else {
1744 if (tdata > -256 && tdata < 256)
1745 debug("%i", (int)tdata);
1746 else
1747 debug("0x%llx", (long long)tdata);
1748 }
1749 }
1750 debug(">");
1751 break;
1752 case PPC_HI6_59:
1753 xo = (iword >> 1) & 1023;
1754 /* NOTE: Some floating point instructions only use the
1755 lowest 5 bits of xo, some use all 10 bits! */
1756 switch (xo & 31) {
1757 case PPC_59_FDIVS:
1758 case PPC_59_FSUBS:
1759 case PPC_59_FADDS:
1760 case PPC_59_FMULS:
1761 case PPC_59_FMADDS:
1762 rt = (iword >> 21) & 31;
1763 ra = (iword >> 16) & 31;
1764 rb = (iword >> 11) & 31;
1765 rs = (iword >> 6) & 31; /* actually frc */
1766 rc = iword & 1;
1767 switch (xo & 31) {
1768 case PPC_59_FDIVS: mnem = "fdivs"; break;
1769 case PPC_59_FSUBS: mnem = "fsubs"; break;
1770 case PPC_59_FADDS: mnem = "fadds"; break;
1771 case PPC_59_FMULS: mnem = "fmuls"; break;
1772 case PPC_59_FMADDS: mnem = "fmadds"; break;
1773 }
1774 debug("%s%s\t", mnem, rc? "." : "");
1775 switch (xo & 31) {
1776 case PPC_59_FMULS:
1777 debug("f%i,f%i,f%i", rt, ra, rs);
1778 break;
1779 case PPC_59_FMADDS:
1780 debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1781 break;
1782 default:debug("f%i,f%i,f%i", rt, ra, rb);
1783 }
1784 break;
1785 default:/* TODO: similar to hi6_63 */
1786 debug("unimplemented hi6_59, xo = 0x%x", xo);
1787 }
1788 break;
1789 case PPC_HI6_63:
1790 xo = (iword >> 1) & 1023;
1791 /* NOTE: Some floating point instructions only use the
1792 lowest 5 bits of xo, some use all 10 bits! */
1793 switch (xo & 31) {
1794 case PPC_63_FDIV:
1795 case PPC_63_FSUB:
1796 case PPC_63_FADD:
1797 case PPC_63_FMUL:
1798 case PPC_63_FMSUB:
1799 case PPC_63_FMADD:
1800 rt = (iword >> 21) & 31;
1801 ra = (iword >> 16) & 31;
1802 rb = (iword >> 11) & 31;
1803 rs = (iword >> 6) & 31; /* actually frc */
1804 rc = iword & 1;
1805 switch (xo & 31) {
1806 case PPC_63_FDIV:
1807 mnem = power? "fd" : "fdiv"; break;
1808 case PPC_63_FSUB:
1809 mnem = power? "fs" : "fsub"; break;
1810 case PPC_63_FADD:
1811 mnem = power? "fa" : "fadd"; break;
1812 case PPC_63_FMUL:
1813 mnem = power? "fm" : "fmul"; break;
1814 case PPC_63_FMSUB:
1815 mnem = power? "fms" : "fmsub"; break;
1816 case PPC_63_FMADD:
1817 mnem = power? "fma" : "fmadd"; break;
1818 }
1819 debug("%s%s\t", mnem, rc? "." : "");
1820 switch (xo & 31) {
1821 case PPC_63_FMUL:
1822 debug("f%i,f%i,f%i", rt, ra, rs);
1823 break;
1824 case PPC_63_FMADD:
1825 debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1826 break;
1827 default:debug("f%i,f%i,f%i", rt, ra, rb);
1828 }
1829 break;
1830 default:rt = (iword >> 21) & 31;
1831 ra = (iword >> 16) & 31;
1832 rb = (iword >> 11) & 31;
1833 rc = iword & 1;
1834 switch (xo) {
1835 case PPC_63_FCMPU:
1836 case PPC_63_FRSP:
1837 case PPC_63_FCTIWZ:
1838 case PPC_63_FNEG:
1839 case PPC_63_FMR:
1840 case PPC_63_FNABS:
1841 case PPC_63_FABS:
1842 switch (xo) {
1843 case PPC_63_FCMPU: mnem = "fcmpu"; break;
1844 case PPC_63_FCTIWZ:
1845 mnem = power? "fcirz" : "fctiwz"; break;
1846 case PPC_63_FRSP: mnem = "frsp"; break;
1847 case PPC_63_FNEG: mnem = "fneg"; break;
1848 case PPC_63_FMR: mnem = "fmr"; break;
1849 case PPC_63_FNABS: mnem = "fnabs"; break;
1850 case PPC_63_FABS: mnem = "fabs"; break;
1851 }
1852 debug("%s%s\t", mnem, rc? "." : "");
1853 switch (xo) {
1854 case PPC_63_FCMPU:
1855 debug("%i,f%i,f%i", rt >> 2, ra, rb);
1856 break;
1857 case PPC_63_FCTIWZ:
1858 case PPC_63_FRSP:
1859 case PPC_63_FNEG:
1860 case PPC_63_FMR:
1861 case PPC_63_FNABS:
1862 case PPC_63_FABS:
1863 debug("f%i,f%i", rt, rb);
1864 break;
1865 default:debug("f%i,f%i,f%i", rt, ra, rb);
1866 }
1867 break;
1868 case PPC_63_MFFS:
1869 debug("mffs%s\tf%i", rc?".":"", rt);
1870 break;
1871 case PPC_63_MTFSF:
1872 ra = (iword >> 17) & 255; /* flm */
1873 debug("mtfsf%s\t0x%02x,f%i", rc?".":"", ra, rb);
1874 break;
1875 default:debug("unimplemented hi6_63, xo = 0x%x", xo);
1876 }
1877 }
1878 break;
1879 default:
1880 /* TODO */
1881 debug("unimplemented hi6 = 0x%02x", hi6);
1882 }
1883
1884 debug("\n");
1885 return sizeof(iword);
1886 }
1887
1888
1889 /*
1890 * debug_spr_usage():
1891 *
1892 * Helper function. To speed up overall development speed of the emulator,
1893 * all SPR accesses are allowed. This function causes unknown/unimplemented
1894 * SPRs to give a warning.
1895 */
1896 static void debug_spr_usage(uint64_t pc, int spr)
1897 {
1898 static uint32_t spr_used[1024 / sizeof(uint32_t)];
1899 static int initialized = 0;
1900
1901 if (!initialized) {
1902 memset(spr_used, 0, sizeof(spr_used));
1903 initialized = 1;
1904 }
1905
1906 spr &= 1023;
1907 if (spr_used[spr >> 2] & (1 << (spr & 3)))
1908 return;
1909
1910 switch (spr) {
1911 /* Known/implemented SPRs: */
1912 case SPR_XER:
1913 case SPR_LR:
1914 case SPR_CTR:
1915 case SPR_DSISR:
1916 case SPR_DAR:
1917 case SPR_DEC:
1918 case SPR_SDR1:
1919 case SPR_SRR0:
1920 case SPR_SRR1:
1921 case SPR_SPRG0:
1922 case SPR_SPRG1:
1923 case SPR_SPRG2:
1924 case SPR_SPRG3:
1925 case SPR_PVR:
1926 case SPR_DMISS:
1927 case SPR_DCMP:
1928 case SPR_HASH1:
1929 case SPR_HASH2:
1930 case SPR_IMISS:
1931 case SPR_ICMP:
1932 case SPR_DBSR:
1933 case SPR_PIR:
1934 break;
1935 default:if (spr >= SPR_IBAT0U && spr <= SPR_DBAT3L) {
1936 break;
1937 } else
1938 fatal("[ using UNIMPLEMENTED spr %i (%s), pc = "
1939 "0x%llx ]\n", spr, ppc_spr_names[spr] == NULL?
1940 "UNKNOWN" : ppc_spr_names[spr], (long long)pc);
1941 }
1942
1943 spr_used[spr >> 2] |= (1 << (spr & 3));
1944 }
1945
1946
1947 /*
1948 * update_cr0():
1949 *
1950 * Sets the top 4 bits of the CR register.
1951 */
1952 void update_cr0(struct cpu *cpu, uint64_t value)
1953 {
1954 int c;
1955
1956 if (cpu->cd.ppc.bits == 64) {
1957 if ((int64_t)value < 0)
1958 c = 8;
1959 else if ((int64_t)value > 0)
1960 c = 4;
1961 else
1962 c = 2;
1963 } else {
1964 if ((int32_t)value < 0)
1965 c = 8;
1966 else if ((int32_t)value > 0)
1967 c = 4;
1968 else
1969 c = 2;
1970 }
1971
1972 /* SO bit, copied from XER: */
1973 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1974
1975 cpu->cd.ppc.cr &= ~((uint32_t)0xf << 28);
1976 cpu->cd.ppc.cr |= ((uint32_t)c << 28);
1977 }
1978
1979
1980 #include "memory_ppc.c"
1981
1982
1983 #include "tmp_ppc_tail.c"
1984
1985

  ViewVC Help
Powered by ViewVC 1.1.26