/[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 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 46541 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26