/[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 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (13 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 48189 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26